как к синтезируемому тексту, чтобы и экранировать и зарегистрировать в сценарии оболочки?

На самом деле, O_DIRECT необходим для предотвращения любого из

  • загрязнение кэша — иногда Вы знаете, что нет никакого смысла в издержках с кэшированием, для, например, при контакте с действительно большими файлами скажите 64 гибибайта, когда существует только 2 гибибайта RAM. Файл потока 32 гибибайт, которые пользователь решил проверить, кажется, не хороший кандидат на кэширование. Это - просто дополнительное действие со своими собственными издержками. И это может заставить некоторые действительно полезные данные быть сокращенными от кэша.
  • дважды кэширование — для, например, некоторый RDBMSes (MySQL для упоминания) допускает определение его собственного кэша. Базы данных, предположительно, знают лучше, как кэшироваться и что, чем Виртуальная память ядра, которая не знает вещь о SQL, планирующем и так далее.

— который бесполезен, как это кажется. И O_DIRECT не означает быть быстрее, часто это не.

49
26.06.2013, 12:36
4 ответа

Это работает:

command | tee -a "$log_file"

tee сохраняет вход в файл (использование -a добавлять, а не перезаписывать), и копии вход к стандартному выводу также.

72
27.01.2020, 19:34

Вы можете использовать here-doc и . source для эффективной, дружественной POSIX модели общего коллектора.

. 8<<-\IOHERE /proc/self/fd/8

command
… 
fn() { declaration ; } <<WHATEVER
# though a nested heredoc might be finicky
# about stdin depending on shell
WHATEVER
cat -u ./stdout | ./works.as >> expect.ed
IOHERE

Когда вы открываете heredoc, вы сигнализируете оболочке с помощью входного маркера IOHERE, что она должна перенаправить свой вход в указанный вами файл-дескриптор, пока не встретит другой конец вашего маркера-ограничителя. Я посмотрел вокруг, но не увидел много примеров использования номера fd перенаправления, как я показал выше, в сочетании с оператором heredoc, хотя его использование четко указано в руководстве по базовым shell-командам POSIX. Большинство людей просто указывают его на stdin и стреляют, но я обнаружил, что создание скриптов таким образом позволяет сохранить stdin свободным, а входящие в состав приложения не жалуются на заблокированные пути ввода/вывода.

Содержимое heredoc транслируется в указанный вами дескриптор файла, который, в свою очередь, интерпретируется как shell-код и выполняется встроенной командой ., но не без указания конкретного пути для ... Если путь /proc/self вызывает у вас проблемы, попробуйте /dev/fd/n или /proc/$$. Этот же метод, кстати, работает и с трубами:

cat ./*.sh | . /dev/stdin

Вероятно, это по меньшей мере неразумно, чем кажется. Конечно, вы можете сделать то же самое с помощью sh, но цель . - выполнение в текущем окружении оболочки, что, вероятно, то, чего вы хотите, и, в зависимости от вашей оболочки, гораздо больше шансов работать с heredoc, чем со стандартной анонимной трубой.

В любом случае, как вы, вероятно, заметили, я все еще не ответил на ваш вопрос. Но если вы подумаете об этом, то точно так же, как heredoc передает весь ваш код в .'in, он также предоставляет вам единственную, простую, точку выхода:

. 5<<EOIN /dev/fd/5 |\ 
    tee -a ./log.file | cat -u >$(tty)
script
… 
more script
EOIN

Таким образом, весь терминальный stdout любого кода, выполняемого в вашем heredoc, выводится из . как само собой разумеющееся и может быть легко перерезан из одной трубы. Я включил вызов cat без буферизации, потому что мне неясно текущее направление stdout, но это, вероятно, излишне (почти наверняка так оно и есть в любом случае), и трубопровод, вероятно, может закончиться прямо на tee.

Вы также можете усомниться в отсутствии кавычек обратной косой черты во втором примере. Эту часть важно понять до того, как вы приступите к работе, и она может дать вам несколько идей о том, как ее можно использовать. Ограничитель heredoc, заключенный в кавычки (до сих пор мы использовали IOHERE и EOIN, причем первый я заключил в кавычки с обратным слешем, хотя "одинарные" или "двойные" кавычки могли бы служить той же цели), запретит оболочке выполнять любое расширение параметров содержимого, но ограничитель без кавычек оставит содержимое открытым для расширения. Последствия этого, когда ваш heredoc является . sourced, драматичны:

. 3<<HD ${fdpath}/3
: \${vars=$(printf '${var%s=$((%s*2))},' `seq 1 100`)} 
HD
echo $vars
> 4,8,12… 
echo $var1 $var51
> 4 104

Поскольку я не процитировал ограничитель heredoc, оболочка расширила его содержимое по мере считывания и перед тем, как передать полученный файловый дескриптор в . для выполнения. Это привело к тому, что команды были разобраны дважды - во всяком случае, расширяемые команды. Поскольку я заключил в обратную косую черту расширение параметра $vars, оболочка игнорировала его объявление при первом проходе и только удаляла обратную косую черту, чтобы все расширенное содержимое printf могло быть оценено нулем, когда . подставлял скрипт при втором проходе.

Эта функциональность в точности соответствует тому, что может обеспечить опасный встроенный модуль оболочки eval, даже если цитирование гораздо проще обработать в heredoc, чем в eval, и оно может быть столь же опасным. Если вы не планируете это тщательно, то, вероятно, лучше кавычки ограничителя "EOF" сделать по привычке. Просто говорю.

EDIT: Эх, я оглядываюсь назад и думаю, что это слишком большая натяжка. Если ВСЕ, что вам нужно сделать, это объединить несколько выходов в одну трубу, то самый простой метод - это использовать a:

{ or ( command ) list ; } | tee -a ea.sy >>pea.sy

Курсивы будут пытаться запустить содержимое в текущей оболочке, в то время как парены будут выводить содержимое автоматически. Тем не менее, любой может сказать вам это, и, по крайней мере, на мой взгляд, решение . heredoc является гораздо более ценной информацией, особенно если вы хотите понять, как на самом деле работает оболочка.

Удачи!

8
27.01.2020, 19:34

Я нашел этот ответ, когда хотел изменить сценарий установки для записи журнала установки.

Мой сценарий уже заполнен операторами echo, например:

echo "Found OLD run script $oldrunscriptname"
echo "Please run OLD tmunsetup script first!"

И я не хотел, чтобы оператор tee запускал его (или другой сценарий для вызова существующего сценария с тройником), поэтому я написал следующее:

#!/bin/bash
# A Shell subroutine to echo to screen and a log file

LOGFILE="junklog"

echolog()
(
echo $1
echo $1 >> $LOGFILE
)


echo "Going"
echolog "tojunk"

# eof

Итак, теперь в моем исходном скрипте я могу просто изменить «echo» на «echolog», где мне нужен вывод в файле журнала.

3
27.01.2020, 19:34
function write_to_log() {
  echo "$@" 
  echo >> "${log_file_name}"
}

Используйте так:

log_file_name="/some/dir/log_file.log"

function write_to_log() {
  echo "$@" 
  echo >> "${log_file_name}"
}

write_to_log "some text"
do_some_command
write_to_log "more text"
do_other_command

Если вы хотите, чтобы все это записывалось, сделайте следующее

{
  echo "some text"
  do_some_command
  echo "more text"
  do_other_command
} | tee "${log_file_name}"
0
21.04.2020, 21:26

Теги

Похожие вопросы