Захватывать обычный вывод (stdout) вместе с выводом ошибок (stderr)

Захватывать обычный вывод (stdout) вместе с выводом ошибок (stderr)

Есть скрипт, запускаемый через 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, ) имеют опцию, которую можно использовать для сообщения об ошибках в любом компоненте конвейера:mkshpipefail

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

Обратите внимание, что я удалил скобки: нет смысла запускать скрипт в подоболочке.

Связанный контент