%20%D0%B2%D0%BC%D0%B5%D1%81%D1%82%D0%B5%20%D1%81%20%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4%D0%BE%D0%BC%20%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA%20(stderr).png)
Есть скрипт, запускаемый через cron, со следующей строкой:
0 * * * * (/var/script.sh | tee -a /var/script.log)
Как переписать запись cron, чтобы захватывать как нормальный вывод, так stdout
и вывод ошибок stderr
? Они должны быть помещены в разные файлы.
решение1
cron
Задания запускаются sh
по умолчанию, и независимо от того, sh
является ли он Bourne, POSIX sh
или совместимым, синтаксис будет следующим:
0 * * * * /var/script.sh 2>&1 | tee -a /var/script.log
Где |
приводит к параллельному запуску двух команд с каждой стороны, соединенных каналом, при этом stdout (fd 1) левой команды подключен к записывающему концу канала, а stdin (fd 0) правой команды подключен к считывающему концу.
Добавляя 2>&1
к левому, мы получаем fd 2 (stderr), указывающий на тот же ресурс, на который указывает fd 1: конец конвейера для записи, поэтому и нормальный, и ошибочный вывод script.sh
будут направляться в конвейер tee
.
tee
запишет его как в свой stdout (который в случае задания cron является либо каналом, либо временным файлом, который будет использоваться для отправки электронного письма пользователю), так и в script.log
.
Этот синтаксис также работает в fish
оболочке.
С помощью (t)csh
, zsh
или bash
(4.0 или новее) вы также можете сделать:
SHELL=/bin/zsh # or tcsh, bash ...
0 * * * * /var/script.sh |& tee -a /var/script.log
(где SHELL=/bin/zsh
указано, как cron
использовать другую оболочку для интерпретации командных строк).
В fish
, вы бы использовали &|
вместо |&
.
С rc
(когда-то являющимся преемником sh
) или производными синтаксис следующий:
SHELL=/bin/rc # or es, akanga
0 * * * * /var/script.sh >[2=1] | tee -a /var/script.log
С помощью zsh
можно также обойтись без него tee
благодаря его MULT_IOS
особенностям:
SHELL=/bin/zsh
0 * * * * /var/script.sh >&1 2>&2 >>& /var/script.log
Что также имело бы преимущество в сохранении script.sh
статуса выхода , а также сохраняло бы script.sh
отправку stderr в исходный stderr в дополнение к script.log
(хотя это не имеет большого значения в задании cron, где stdout и stderr в любом случае направляются в одно и то же место).
Несколько оболочек типа Bourne/POSIX ( по крайней мере bash
, ksh93
, zsh
, yash
, ) имеют опцию, которую можно использовать для сообщения об ошибках в любом компоненте конвейера:mksh
pipefail
SHELL=/bin/ksh # or zsh, bash...
0 * * * * set -o pipefail && /var/script.sh 2>&1 | tee -a /var/script.log
решение2
cron хочет сообщить вам о любой задаче cron, которая производит вывод. Он хочет отправить вам результаты по электронной почте. Если вы не хотите получать электронную почту от cron, убедитесь, что ваши задачи не производят вывод: не используйте tee
, просто перенаправьте вывод
0 * * * * /var/script.sh >> /var/script.log 2>&1
Обратите внимание, что я удалил скобки: нет смысла запускать скрипт в подоболочке.