Я пытался найти ответ на этот вопрос, но пока не получилось:
У меня есть сценарий, который запускает некоторые другие сценарии, и многие из этих других сценариев содержат «set -x», что заставляет их печатать каждую команду, которую они выполняют. Я хотел бы избавиться от этого, но сохранить информацию, если какой-либо из сценариев отправит сообщение об ошибке в stderr.
Так что я не могу просто написать ./script 2>/dev/null
Кроме того, у меня нет прав для редактирования этих других скриптов, поэтому я не могу вручную изменить опцию set.
Я думал о регистрации всего от stderr до отдельного файла и фильтрации команд трассировки, но, может быть, есть более простой способ?
./script 2>some_file
Ответы:
С
bash
4.1 и выше, вы можете сделать(также работает, когда
bash
вызывается какsh
).По сути, мы говорим
bash
вывестиxtrace
выходные данные по дескриптору файла 7 вместо значения по умолчанию 2 и перенаправить этот дескриптор файла в/dev/null
. Число FD является произвольным. Используйте fd выше 2, который иначе не используется в вашем скрипте. Если оболочка, в которую вы вводите эту команду, - этоbash
илиyash
, вы можете даже использовать число выше 9 (хотя вы можете столкнуться с проблемами, если дескриптор файла используется внутри оболочки).Если оболочка, из которой вы вызываете этот
bash
скриптzsh
, вы также можете сделать:для переменной, которой автоматически присваивается первый свободный fd выше 9.
Для более старых версий
bash
, другой вариант, еслиxtrace
он включен сset -x
(в отличие от#! /bin/bash -x
илиset -o xtrace
), будет переопределятьset
как экспортированную функцию, которая ничего не делает при передаче-x
(хотя это сломало бы скрипт, если он (или любой другойbash
скрипт, который он вызывает) используетсяset
для установки позиционных параметров).Подобно:
Другой вариант - добавить ловушку DEBUG в
$BASH_ENV
файл, который выполняетсяset +x
перед каждой командой.Это не будет работать, когда
set -x
это делается в под-оболочке.Как сказал @ilkkachu, если у вас есть разрешение на запись в любую папку в файловой системе, вы, по крайней мере, сможете сделать копию сценария и отредактировать его.
Если вы нигде не можете написать копию сценария или если вам неудобно создавать и редактировать новую копию каждый раз, когда происходит обновление исходного сценария, вы все равно можете сделать следующее:
Это (и подход к копированию) может не работать должным образом, если сценарий выполняет какие- либо действия с
$0
такими специальными переменными, как$BASH_SOURCE
(например, поиск файлов, относящихся к местоположению самого сценария), поэтому вам может потребоваться выполнить еще какое-то редактирование, например заменить$0
на путь сценария ...источник
{BASH_XTRACEFD}>
Трюк работает вbash
4.1 или более поздней версии , а также.ksh93
илиbash
в том, что переменная не передается в среде команды (сравните<shell> -c 'export fd; printenv fd {fd}> /dev/null'
вzsh
,bash
иksh93
). Вы можете сделать так, чтобы он работал вksh93
/bash
, выполняя это за два шага или, возможно, используяeval
, но дляbash
этого это может иметь побочные эффекты, если включена опция xtrace.Поскольку они являются сценариями, вы можете делать их копии и редактировать их.
Помимо этого, фильтрация выходных данных может показаться простой, вы можете явно установить
PS4
что-то более необычное, чем один плюс, чтобы упростить фильтрацию:(конечно, это рухнет stdout и stdin, но пайпинг просто stderr в Bash становится немного проблематичным, поэтому я проигнорирую это)
источник
PS4="%%%%" bash script.sh 2> >(grep -ve '^%%%%')
.bash
проблемы, так какgrep
он запускается асинхронно (bash его не ждет, поэтому он может (и часто это делает) выводить данные после запуска следующей команды в сценарии).