Используйте тройник . Например:
command 2>&1 | tee file.txt
Который запускает command
перенаправление SDTERR в SDTOUT. tee
копирует STDIN как в STDOUT, так и в файл file.txt
.
В bash вы можете использовать замену процесса следующим образом, чтобы скопировать вывод в$LOG
:
exec &> >(tee $LOG)
Однако этот башизмне будет работать на других оболочках.
./thescript.sh 2>&1 1>/dev/null | sed '1 s/^/error_message_starts:\n/' >> error_log;
Основано на обсуждении здесь и на этом:
https://stackoverflow.com/questions/2342826/how-to-pipe-stderr-and-not-stdout
Для того, чтобы добавить все, что мы хотим. Нам нужно иметь возможность передать поток ошибок (fd2 ). Единственным выводом, который можно передать по каналу, является fd1. Поэтому fd2 нужно перенаправить на fd1. Мы также должны избавиться от fd1, чтобы он не мешал.
Создайте функцию журнала ошибок для ваших скриптов. Что-то вроде:
logerr () {
printf '%s - %s - %s\n' \
"$(date '+%F:%T')" \
"$(basename "$0")" \
"$*" >&2
}
Затем вы вызываете это из своих скриптов, например:
if false; then
: something for pass
else
logerr failed to be false
fi
Кроме того, использование 2>error_log
будет перезаписывать error_log
каждый раз. Вам нужно использовать 2>>error_log
для добавления.
Если вы хотите иметь возможность перехватывать ошибки других команд и регистрировать их, вы можете собрать что-то вроде этого:
#!/bin/bash
logerr () {
local message=$*
if [[ ! -t 0 ]]; then
message=$(</dev/stdin)
fi
if [[ -n "$message" ]]; then
printf '%s - %s - %s\n' \
"$(date '+%F:%T')" \
"$(basename "$0")" \
"$*" >&2
fi
}
ls -lts /fake/path 2>&1 >/dev/tty | logerr
Обеспечение перенаправления стандартного вывода в любое подходящее место, в котором он вам нужен.
Это позволит сценарию logerr
читать со стандартного ввода, если он открыт (, что позволит вам передавать программы в logerr ). Проблема в том, что программы отправляют сообщения об ошибках на stderr, а вы хотите, чтобы они оставались отдельными от stdin.