
В моем скрипте есть эта чрезвычайно простая функция:
# Used for debug tracing.
log()
{
:
echo "log: $1"
}
Идея в том, чтобы иметь возможность настраивать/отключать ведение журнала в одном месте. Очень грубо.
Теперь я хочу, чтобы мой скрипт не производил абсолютно никакого вывода в конфигурации релиза. Единственное решение, которое я придумал, но крайне неСУХОЕ:
TMPFILE='/tmp/tempfilewithpossiblyuniquename'
cmd 1>"$TMPFILE" 2>"$TMPFILE"
cat "$TMPFILE" | xargs log
rm "$TMPFILE"
длякаждая команда. Как это улучшить?
EDIT: Я хочу собратьвсевывести в stdout
и stderr
и направить его через log()
. Затем log()
можно выбрать игнорировать все, записать в файл, распечатать и т. д.
решение1
Во-первых, эта функция будет регистрировать только первое «слово» всего отправленного ей сообщения, поскольку вы используете $1
вместо "$*"
.
Во-вторых, есть (как это часто бывает с POSIX) множество способов сделать что-то подобное. Я бы, наверное, выбрал что-то вроде:
log() {
cat - >> "$logfile"
}
do_stuff | log
Но вы также можете:
(
do_stuff
do_more_stuff
) >> "$logfile"
Что касается полного подавления всего вывода — это то, что обычно лучше оставить для вызывающей среды (например, ./thing 1> /dev/null 2> &1
), а не блокировать его «в коде», как это было. При этом:
squashout="true" # comment this out to stop killing output
if ! [[ "true" = "${squashout-false}" ]]; then
# Redirect stdout and stderr to the null device.
exec 1> /dev/null
exec 2> /dev/null
fi
решение2
Абсолютно никакой вывод не является простым, просто перенаправьте скрипты stdout
и stderr
на /dev/null
:
exec >/dev/null 2>&1
Это повлияет на саму оболочку и любые команды, которые она выполнит после этого. Запустите это условно, чтобы выбрать, куда перенаправлять вывод.
if [ "$output_to_file" = 1 ]; then
exec > "$outputfilename" 2>&1
elif [ "$output_suppress" = 1 ]; then
exec > /dev/null 2>&1
fi
Обратите внимание, что подавлениевсевывод, вероятно, не очень хорошая идея. Пользователь, скорее всего, захочетнекоторыйуведомление об ошибках.
Если вы настаиваете на передаче вывода через функцию (и используете Bash/ksh/Zsh), вы можете использовать подстановку процесса:
#!/bin/bash
mangle_output() {
# do something smarter here
while read -r line; do
echo "output: $line";
done;
}
# redirect stdout and stderr to the function
exec > >(mangle_output) 2>&1
echo something that produces output
Хотя следует отметить, что обработка выходных данных с помощью цикла оболочки — не очень хорошая идея, по крайней мере, это медленно. Смотрите:Почему использование цикла оболочки для обработки текста считается плохой практикой?. Если вам нужно только перенаправить файл или на /dev/null
, просто используйте exec
для настройки перенаправлений.