Подавить трассировку выполнения bash (set -x) снаружи скрипта

Если кто-то столкнется с этой проблемой в будущем, вот как я ее решил. Я только что использовал gmux_backlight +50000, и это сработало отлично.

17
19.03.2017, 01:12
2 ответа

С bash 4.1 и выше, вы можете сделать

BASH_XTRACEFD=7 ./script.bash 7> /dev/null

(также работает, когда bash вызывается как sh).

По сути, мы говорим bash выводить вывод xtrace на файловый дескриптор 7 вместо 2 по умолчанию, и перенаправлять этот файловый дескриптор на /dev/null. Номер fd является произвольным. Используйте fd больше 2, который не используется в вашем сценарии. Если оболочка, в которой вы вводите эту команду, bash или yash, вы можете даже использовать число больше 9 (хотя вы можете столкнуться с проблемами, если дескриптор файла используется внутри оболочки).

Если оболочка, из которой вы вызываете сценарий bash, - zsh, вы также можете сделать:

(export BASH_XTRACEFD; ./script.bash {BASH_XTRACEFD}> /dev/null)

чтобы переменной автоматически присваивалось первое свободное fd больше 9.

Для старых версий bash, другой вариант, если xtrace включен с помощью set -x (в отличие от #! /bin/bash -x или set -o xtrace) было бы переопределить set как экспортируемую функцию, которая ничего не делает при передаче -x (хотя это сломает скрипт, если он (или любой другой скрипт bash, который он вызывает) использует set для установки позиционных параметров).

Например:

set()
  case $1 in
    (-x) return 0;;
    (-[!-]|"") builtin set "$@";;
    (*) echo >&2 That was a bad idea, try something else; builtin set "$@";;
  esac

export -f set
./script.bash

Другой вариант - добавить ловушку DEBUG в файл $BASH_ENV, который делает set +x перед каждой командой.

echo 'trap "{ set +x; } 2>/dev/null" DEBUG' > ~/.no-xtrace
BASH_ENV=~/.no-xtrace ./script.bash

Однако это не будет работать, когда set -x выполняется во вложенной оболочке.

Как сказал @ilkkachu, если у вас есть права на запись в любую папку в файловой системе, вы должны иметь возможность сделать копию скрипта и отредактировать его.

Если вам некуда записать копию скрипта, или если вам не удобно создавать и редактировать новую копию каждый раз, когда происходит обновление оригинального скрипта, вы все равно сможете это сделать:

 bash <(sed 's/set -x/set +x/g' ./script.bash)

Этот способ (и способ копирования) может работать неправильно, если скрипт делает что-нибудь причудливое с $0 или специальными переменными типа $BASH_SOURCE (например, ищет файлы, относительные к расположению самого скрипта), поэтому вам может понадобиться дополнительное редактирование, например, заменить $0 на путь к скрипту. ..

25
27.01.2020, 19:46

Поскольку это скрипты, вы могли бы сделать их копии и отредактировать их.

В остальном, фильтрация вывода кажется простой, вы можете явно установить PS4 на что-то более необычное, чем один плюс, чтобы облегчить фильтрацию:

PS4="%%%%" bash script.sh 2>&1 | grep -ve '^%%%%'

(конечно, это приведет к разрушению stdout и stdin, но использование только stderr в Bash становится немного неприятным, поэтому я проигнорирую это)

5
27.01.2020, 19:46

Теги

Похожие вопросы