Отправлять вывод bash -x в лог-файл без прерывания стандартного вывода

12

Есть ли способ отправить информацию, отображаемую, запустив bash-скрипт с параметром -x, в файл, не изменяя при этом стандартный вывод, увиденный пользователем, выполняющим скрипт?

Это функция отладки, которую я хотел бы реализовать в используемом нами скрипте bash, который часто меняется.

Очень признателен.

извините доктор розовый
источник

Ответы:

21

Вывод из -x идет в stderr, а не в stdout. Но даже это может быть проблемой - множество сценариев будут иметь функциональные зависимости от содержимого stderr, и в некоторых случаях смешивать потоки отладки и stderr довольно сложно.

Версии Bash> 4.1 предлагают другое решение: переменная среды BASH_XTRACEFD позволяет вам указать файловый дескриптор, который будет использоваться для отправки потока отладки. Это может быть файл или канал или любое другое unix-y качество, которое вам нравится.

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

Немного повозившись, вы можете делать другие вещи - например, делать «тройник» для потоков stdout и / или stdin и чередовать их с выходными данными отладки, чтобы ваш журнал был более полным. Подробнее об этом см. Https://stackoverflow.com/questions/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself .

Большим преимуществом этого подхода перед альтернативами является то, что вы не рискуете изменить поведение вашего скрипта, вставляя выходные данные отладки в stdout или stderr.

Stabledog
источник
Смотрите также здесь о том, как найти неиспользуемый дескриптор файла для файла.
Ярно
Нужно ли закрывать файловый дескриптор (т.е. строку exec 19>&-)? По моему опыту он закрывается автоматически, когда скрипт заканчивается.
Ярно
1
Приведенный выше код не предполагает, что вы запускаете скрипт, или какой длины он может быть, и т. Д. Это правда, что если вы просто делаете то, что делает этот фрагмент, и помещаете это в скрипт, дескриптор файла будет быть закрытым только потому, что вся оболочка исчезает в конце скрипта. Так что в этом случае вам не нужно закрывать ручку. Но в целом при кодировании против ресурса хорошей практикой является закрытие того, что вы открыли, потому что тогда ваш код можно использовать в более широком контексте, где ведение домашнего хозяйства с большей вероятностью будет иметь значение.
Конюшня
Почему вы экспортируете BASH_XTRACEFD? Почему бы просто не установить значение для него?
Ярно
В любом случае, альтернативный способ закрыть дескриптор файла - установить новое значение (например, null) для BASH_XTRACEFD или сбросить его.
Ярно
4

set -xничего не отправляет на стандартный вывод, так что проблем нет. Что он делает, так это пишет в стандартную ошибку, которая отправляется на консоль по умолчанию.

Что вы хотите сделать, это перенаправить стандартный вывод в другой файл, например так:

/bin/sh -x /my/script/file 2>/my/log/file
ombble
источник
1

См man tee.

Вы запускаете его как, tee commandname filenameи он будет отображать выводимые команды stdoutи также записывать их в filename.

Свен
источник