Як повторювати команди оболонки під час їх виконання


910

Як у скрипті оболонки я можу повторювати всі викликані команди оболонки та розширювати будь-які назви змінних?

Наприклад, подано наступний рядок:

ls $DIRNAME

Я хотів би, щоб сценарій запускав команду і відображав наступне

ls /full/path/to/some/dir

Мета - збереження журналу всіх викликаних команд оболонок та їх аргументів. Чи може бути кращий спосіб генерування такого журналу?

Відповіді:


1041

set -xабо set -o xtraceрозширює змінні та друкує перед рядком маленький знак +.

set -vабо set -o verboseне розширює змінні перед друком.

Використовуйте set +xта set +vвимкніть вищевказані налаштування.

У першому рядку сценарію можна поставити #!/bin/sh -x(або -v) мати такий же ефект, що і set -x(або -v) пізніше у сценарії.

Сказане також працює з /bin/sh.

Перегляньте вікі bash-хакерів щодо 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
що робити, якщо я хочу розфарбувати команду, коли лунає, щоб диференціювати команду та її результати?
Льюїс Чан

10
Що робити, якщо я хочу, щоб вона співала кожну команду через синтезатор мовлення, схожий на вокалоїд, коли лунає, щоб я міг чути, що це робить здалеку, а також насолоджуватися музикою? Можливо, іншим голосом для входів і виходів.
ADJenks

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

316

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 за допомогою нижньої оболонки є найбільш зручним.
Brent Faust

Це те, що я шукаю! Ні set +x, це впливає на всі команди, що занадто багато!
Хлунг

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

2
Мені не подобається ця відповідь. Є безліч крайових випадків, коли те, що ви бачите, - це не те, що ви отримуєте (особливо з пробілами, цитатами, символами, що утекли, замінами змінних / виразів тощо), тому не сліпо вставляйте команду "Ехо" в термінал і не припускайте, що вона запуститься так само. Крім того, друга техніка - це просто злом, і вона викреслить інші екземпляри слова 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результатів.
Brent Faust

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

Відповідно до Посібника з Bash для початківців TLDP : Розділ 2. Написання та налагодження сценаріїв :

2.3.1. Налагодження всього сценарію

$ bash -x script1.sh

...

Зараз є повноцінний налагоджувач для Bash, доступний на SourceForge . Ці функції налагодження доступні в більшості сучасних версій 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_

4

За зш, відлуння

 setopt VERBOSE

А для налагодження,

 setopt XTRACE

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плюс Soth 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.