Как отобразить команды оболочки при их выполнении


913

В сценарии оболочки, как я повторяю все вызванные команды оболочки и раскрываю имена любых переменных?

Например, с учетом следующей строки:

ls $DIRNAME

Я хотел бы, чтобы скрипт запускал команду и отображал следующее

ls /full/path/to/some/dir

Цель - сохранить журнал всех вызванных команд оболочки и их аргументов. Возможно, есть лучший способ создания такого журнала?

Ответы:


1044

set -xили set -o xtraceраскрывает переменные и печатает маленький знак + перед строкой.

set -vили set -o verboseне раскрывает переменные перед печатью.

Используйте set +xи set +vдля отключения вышеуказанных настроек.

В первой строке скрипта можно поставить #!/bin/sh -x(или -v), чтобы иметь тот же эффект, что и set -x(или -v) позже в скрипте.

Выше также работает с /bin/sh.

Смотрите вики bash-hackers об setатрибутах и об отладке .

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

$ bash -x shl 
+ DIR=/tmp/so
+ ls /tmp/so
$

7
Если вы хотите увидеть, пронумерованные строки выполняется см stackoverflow.com/a/17805088/1729501
user13107

3
Что делать, если я хочу раскрасить команду при отражении, чтобы дифференцировать команду и вывод ее результатов?
Льюис Чен,

11
Что, если я хочу, чтобы он эхом пел каждую команду через вокалоидный синтезатор речи, чтобы я мог слышать, что он делает на расстоянии, а также наслаждаться музыкой? Возможно, другим голосом для входов и выходов.
ADJenks

(АБС имеет долгую историю отсутствия ответа на запросы об исправлении примеров плохой практики, вплоть до того, что давние давние члены сообщества создавали конкурирующие ресурсы; перемещали ссылки на вики bash-хакеров - вики Wooledge или Официальное руководство Bash также будет лучше ресурсов).
Чарльз Даффи

317

set -x даст вам то, что вы хотите.

Вот пример сценария оболочки для демонстрации:

#!/bin/bash
set -x #echo on

ls $PWD

Это расширяет все переменные и печатает полные команды перед выводом команды.

Вывод:

+ ls /home/user/
file1.txt file2.txt

21
Использование слова «многословно» таким образом ничего не дает. Вы можете сделать set -o verboseили set -v(только «многословный») или set -o xtraceили set -x(только «xtrace») или set -xv(оба) или set -o xtrace -o verbose(оба).
Приостановлено до дальнейшего уведомления.

это работает хорошо, но имейте в виду, что "многословный" перезаписывает 1 доллар
JasonS

90

Я использую функцию для вывода и запуска команды:

#!/bin/bash
# Function to display commands
exe() { echo "\$ $@" ; "$@" ; }

exe echo hello world

Какие выводы

$ echo hello world
hello world

Для более сложных командных каналов и т. Д. Вы можете использовать eval:

#!/bin/bash
# Function to display commands
exe() { echo "\$ ${@/eval/}" ; "$@" ; }

exe eval "echo 'Hello, World!' | cut -d ' ' -f1"

Какие выводы

$  echo 'Hello, World!' | cut -d ' ' -f1
Hello

Не много голосов за этот ответ. Есть ли причина, по которой это плохая идея? Работал на меня, и, кажется, это именно то, что я ищу ...
fru1tbat

1
Это лучший ответ, если вы не хотите печатать каждую команду. Это позволяет избежать ++ set +xвыхода при выключении, а также выглядит чище. Однако для одного или двух утверждений ответ bhassel с использованием подоболочки является наиболее удобным.
Брент Фауст

Это то, что я ищу! Нет set +x, это влияет на все команды, что слишком много!
Хлунг

11
Основным недостатком этого является то, что выходные данные теряют информацию о цитировании. Вы не можете различить cp "foo bar" bazи cp foo "bar baz", например. Так что это хорошо для отображения информации о прогрессе для пользователя; меньше для отладки вывода или записи воспроизводимых команд. Различные варианты использования. В zsh, вы можете сохранить цитаты с :qмодификатором:exe() { echo '$' "${@:q}" ; "$@" ; }
Эндрю Янке

2
Мне не нравится этот ответ. Существует множество крайних случаев, когда вы видите не то, что получаете (особенно с пробелами, кавычками, экранированными символами, подстановками переменных / выражений и т. Д.), Поэтому не вставляйте вслепую команду echoed в терминал и предполагайте, что она будет работать так же. Кроме того, вторая техника - это просто взлом, и она удалит другие слова evalиз вашей команды. Так что не ожидайте, что он будет работать должным образом exe eval "echo 'eval world'"!
mwfearnley

88

Вы также можете переключать это для выбранных строк в вашем скрипте, оборачивая их set -xи set +x, например,

#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
   echo "grabbing $URL"
   set -x
   curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
   set +x
fi

54

Ответ shuckc на вывод выбранных строк имеет несколько недостатков: в конечном итоге вы set +xполучаете следующую команду и теряете возможность тестировать код выхода с помощью$? поскольку он перезаписывается командой set +x.

Другой вариант - запустить команду в подоболочке:

echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )

if [ $? -eq 0 ] ; then
    echo "curl failed"
    exit 1
fi

который даст вам вывод, как:

getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed

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


7
Хороший способ избежать ++ set +xвывода.
Брент Фауст

3
Еще лучше: заменить if [ $? -eq 0 ]на if (set -x; COMMAND).
Амеди Ван

35

Другой вариант - поставить «-x» в верхней части скрипта, а не в командной строке:

$ cat ./server
#!/bin/bash -x
ssh user@server

$ ./server
+ ssh user@server
user@server's password: ^C
$

Обратите внимание, что это не похоже на работу между ./myScriptи bash myScript. Еще хорошо отметить, спасибо.
altendky

27

Согласно TLDP «s Guide Bash для начинающих: Глава 2. Разработка и отладка скриптов :

2.3.1. Отладка всего скрипта

$ bash -x script1.sh

...

Теперь на SourceForge доступен полноценный отладчик для Bash . Эти функции отладки доступны в большинстве современных версий Bash, начиная с 3.x.

2.3.2. Отладка части (частей) скрипта

set -x            # Activate debugging from here
w
set +x            # Stop debugging from here

...

Таблица 2-1. Обзор установленных опций отладки

    Short  | Long notation | Result
    -------+---------------+--------------------------------------------------------------
    set -f | set -o noglob | Disable file name generation using metacharacters (globbing).
    set -v | set -o verbose| Prints shell input lines as they are read.
    set -x | set -o xtrace | Print command traces before executing command.

...

В качестве альтернативы, эти режимы могут быть указаны в самом скрипте, добавляя нужные параметры в объявление оболочки первой строки. Опции можно комбинировать, как это обычно бывает с командами UNIX:

#!/bin/bash -xv

18

Введите «bash -x» в командной строке перед именем сценария Bash. Например, чтобы выполнить foo.sh, введите:

bash -x foo.sh

11

Вы можете выполнить скрипт Bash в режиме отладки с -xопцией .

Это будет повторять все команды.

bash -x example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

Вы также можете сохранить опцию -x в скрипте . Просто укажите -xопцию в шебанге.

######## example_script.sh ###################
#!/bin/bash -x

cd /home/user
mv text.txt mytext.txt

##############################################

./example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

2
Также bash -vxбудет делать то же самое, но без интерполяции переменных
loa_in_


2

Для cshи tcsh, вы можете set verboseили set echo(или вы можете даже установить оба, но это может привести к некоторому дублированию в большинстве случаев).

verboseОпция печатает довольно много точное выражение оболочки , что вы печатаете.

echoВариант более показателен , что будет выполняться через нерест.


http://www.tcsh.org/tcsh.html/Special_shell_variables.html#verbose

http://www.tcsh.org/tcsh.html/Special_shell_variables.html#echo


Special shell variables

verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.



1

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

Без оценки

exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt

Выходы:

$
file.txt

С eval:

exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'

Какие выводы

$ exe eval 'ls -F | grep *.txt'
file.txt
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.