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


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.