У меня есть скрипт, который измеряет, как долго выполняется какая-то команда.
Ему нужна «настоящая» time
команда, то есть двоичный файл, например, в /usr/bin/time
(поскольку встроенный bash не имеет -f
флага).
Ниже приведен упрощенный скрипт, который можно отлаживать:
#!/bin/bash
TIMESEC=$(echo blah | ( /usr/bin/time -f %e grep blah >/dev/null ) 2>&1 | awk -F. '{print $1}')
echo ABC--$TIMESEC--DEF
if [ "$TIMESEC" -eq 0 ] ; then
echo "we are here!"
fi
Сохраните как «test.sh» и выполните:
$ bash test.sh
ABC--0--DEF
we are here!
Так это сработало.
Теперь давайте попробуем отладить это, добавив «-x» в командную строку bash:
$ bash -x test.sh
++ echo blah
++ awk -F. '{print $1}'
+ TIMESEC='++ /usr/bin/time -f %e grep blah
0'
+ echo ABC--++ /usr/bin/time -f %e grep blah 0--DEF
ABC--++ /usr/bin/time -f %e grep blah 0--DEF
+ '[' '++ /usr/bin/time -f %e grep blah
0' -eq 0 ']'
test.sh: line 10: [: ++ /usr/bin/time -f %e grep blah
0: integer expression expected
Почему этот скрипт ломается, когда мы используем "-x", и прекрасно работает без него?
bash
shell-script
Томаш Хмелевски
источник
источник
-x
on, что$()
конструкция получает-x
вывод, включенный как часть его результирующего значения. Не знаю, является ли это "ожидаемым" поведением или ошибкой ... Или, может быть, именно()
внутренняя оболочка фактически дает-x
результат.BASH_XTRACEFD
позволяет перенаправитьset -x
вывод туда, где меньше проблем.Ответы:
Проблема в этой строке:
где вы перенаправляете стандартную ошибку, чтобы соответствовать стандартному выводу. bash записывает свои сообщения трассировки в стандартную ошибку и (например) использует свой встроенный модуль
echo
вместе с другими конструкциями оболочки в процессе bash.Если вы измените его на что-то вроде
это обойдет эту проблему и, возможно, станет приемлемым компромиссом между трассировкой и работой:
источник
Вы также можете просто уронить подоболочку. по-видимому, именно вложенные оболочки обижают друг друга:
Если вы делаете:
... вы запускаете подоболочку, запущенную для обработки той части конвейера, в которой находится подоболочка. Поскольку оболочка без перенаправления даже отладочных выходных данных подоболочки внутри (как это было бы также для любой другой
{
составной команды, которую; } >redirect
вы могли бы выбрать) для своей секции конвейера, вы смешиваете потоки. Это связано с порядком перенаправления.Вместо этого, если вы просто сначала перенаправите только вывод ошибок команд, которые вы пытаетесь выполнить, и позволите выводу оболочки хоста перейти в stderr, вы не столкнетесь с такой же проблемой.
и так...
... оболочка хоста может продолжать писать свой stderr там, где пожелает, при этом перенаправляя только вывод команд, которые она вызывает, в канал.
В этом отношении...
источник