В настоящее время я использую следующую настройку для перенаправления вывода нескольких команд:
echo "Some normal commands"
(
echo "Error: something happened"
echo "Warning: this incident will be logged"
) >> logfile
echo "More normal commands"
Это довольно полезно, и это также работает с трубами.
Это лучший способ сделать это? Есть ли альтернатива, которую я должен рассмотреть?
bash
shell-script
io-redirection
wchargin
источник
источник
:)
Ответы:
Альтернативой является использование скобок вместо скобок. Это изменение выполняет команды в текущей оболочке, а не в подоболочке
ссылка: https://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping
Это особенно актуально, когда вы изменяете переменные внутри группы:
источник
{ }
но не( )
.)(echo msg1; echo msg2)
- но с фигурными скобками, это должно быть{ echo msg1; echo msg2;}
, с пробелом после{
и точка с запятой (;
) или амперсанд (&
) перед}
.Ответ Гленна хороший - различие между
( ... )
и{ ... }
важно.Одна из стратегий, которую я часто использую для вывода ошибок, например, в вашем вопросе, это
tee
команда Вы могли бы сделать что-то вроде этого:Команда
tee
отправит вывод в два места;-a
опция «добавляет» вывод в именованный файл, и команда также передает ввод в стандартный вывод. В>&2
конце строки перенаправляетtee
stdout в stderr, который может обрабатываться по-разному (например, в задании cron).Еще один совет, который я часто использую в сценариях оболочки, - это изменение поведения отладочной или подробной информации в зависимости от того, выполняется ли сценарий на терминале или имеет
-v
опцию. Например:Сценарии могут начинаться с чего-то общего, подобного этому, сверху, с подробным и отладочным выводом, разбросанным по всему сценарию. Это всего лишь один из способов сделать это - их много, и у разных людей будет свой собственный способ справиться с этим, особенно если они уже давно. :)
Еще один вариант - обработать вывод с помощью «обработчика» - функции оболочки, которая может делать более умные вещи. Например:
(Обратите внимание, что
${var^^}
только для bash.)Это создает функцию оболочки, которая может использовать функции вашей системы
syslog
(сlogger
командой) to send things to system logs. The
logme () `функция может использоваться либо с опциями, которые генерируют отдельные строки данных журнала, либо с несколькими строками ввода, которые обрабатываются в stdin. Поиграйте с ней, если она кажется привлекательнымОбратите внимание, что это пример, и, вероятно, его не следует копировать дословно, если вы не понимаете его и не знаете, что он делает именно то, что вам нужно. Лучшая идея - взять концепции и реализовать их самостоятельно в своих собственных сценариях.
источник
function log () { cat >> $logfile }
, который в основном является более простой версией вашегоlogme
.ts(1)
; Использование:{ printf '%s\n' "Warning text"; printf '%s\n' "This event will be logged"; } | ts '[%Y-%m-%d %T]' | tee -a "$logfile" >&2
.ts(1)
не установлен на системах, которые я использую - FreeBSD, OSX и старый Ubuntu. Можете ли вы сказать нам, что это обеспечивает?sponge(1)
(запись в файл только после закрытия stdin, так что вы можете обойтисьsomething < foo | sponge foo
без зазубринfoo
при перенаправлении) иvipe(1)
(вставка текстового редактора в канал).Более подходящий способ сделать это с
{ command; }
, чем(command)
. Причина в том, что когда команды сгруппированы с()
подоболочкой, открывается для выполнения этих команд, и, следовательно, переменные, которые инициализируются во время этого блока, не будут доступны для других разделов скрипта.Вместо этого, когда мы используем
{}
для группировки команд, команды выполняются в той же оболочке, и, следовательно, переменные будут доступны для других разделов скрипта.Здесь, когда этот раздел выполняется,
$var
переменная сохраняет свое значение, а в другом случае - нет.источник
{ command; }
.