2010-05-18 164 views
536

在shell腳本中,我如何回顯所有調用的shell命令並展開所有變量名稱? 例如,給出以下行:在shell腳本中:執行echo shell命令

ls $DIRNAME 

我想腳本來運行該命令,並顯示以下

ls /full/path/to/some/dir 

目的是保存日誌的所有shell命令的調用,其參數。也許有更好的方法來生成這樣一個日誌?

回答

598

set -xset -o xtrace展開變量並在行之前打印一個+號。

set -vset -o verbose在打印前不擴展變量。使用set +xset +v來關閉上述設置。

在腳本的第一行中,一個可以把#!/bin/sh -x(或-v)具有相同的效果set -x(或-v)後面的腳本。

以上也適用於/bin/sh

http://www.faqs.org/docs/abs/HTML/options.html

$ cat shl 
#!/bin/bash                  

DIR=/tmp/so 
ls $DIR 

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

set -x會給你想要的東西。

下面是一個例子外殼腳本來證明:

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

ls $PWD 

這擴大所有變量和指令的輸出之前打印的全部命令。

輸出:

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

使用單詞 「詳細」 這樣不會完成任何事情。你可以執行'set -o verbose'或'set -v'(只有「verbose」)或'set -o xtrace'或'set -x'(只有「xtrace」)或'set -xv'(兩者)或'set -o xtrace -o verbose'(兩者)。 – 2010-05-18 01:03:05

+0

這很好,但請注意,「詳細」會覆蓋$ 1 – JasonS 2013-06-13 02:04:48

+0

@jasonS *。但是,我沒有想到,好, – Wyatt8740 2016-07-12 18:03:39

67

您還可以通過在set -xset +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 
27

另一種選擇是把「-X」在你的腳本的頂部,而不是在命令行中:(代表不足,無法發表評論,選擇的答案)

$ cat ./server 
#!/bin/bash -x 
ssh [email protected] 

$ ./server 
+ ssh [email protected] 
[email protected]'s password: ^C 
$ 

+0

請注意,這似乎並沒有在'./myScript'和'bash myScript'之間完全相同。還有一件好事要指出,謝謝。 – altendky 2015-04-16 14:08:39

3

對於zsh的呼應

setopt VERBOSE 

和調試

setopt XTRACE 
34

shuckc的回送選擇線路的答案有幾個缺點:你最終有以下set +x命令被回送爲好,你失去與$?測試退出代碼,因爲它得到由set +x覆蓋的能力。

另一種選擇是在子shell中運行以下命令:

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 

這確實招致了命令創建一個新的子shell的開銷,雖然。

+6

避免++集+ x輸出的好方法。 – 2015-01-09 15:23:35

+2

甚至更​​好:替換'if [$? -eq 0]'帶'if(set -x; COMMAND)'。 – 2017-01-02 10:35:57

14

在bash腳本的名稱之前的命令行中鍵入「bash -x」。例如,爲了執行foo.sh,類型:

bash -x foo.sh 
55

使用函數來呼應然後運行命令

#!/bin/bash 
#function to display commands 
exe() { echo "\$ [email protected]" ; "[email protected]" ; } 

exe echo hello world 

其輸出

$ echo hello world 
hello world 

編輯:

對於更復雜的命令管道等,你可以使用eval:

#!/bin/bash 
#function to display commands 
exe() { echo "\$ ${@/eval/}" ; "[email protected]" ; } 

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

,輸出

$ echo 'Hello World' | cut -d ' ' -f1 
Hello 
+0

很少這個答案的投票。這是一個壞主意嗎?爲我工作,似乎正是我正在尋找... – fru1tbat 2014-07-22 14:03:57

+1

這是最好的答案,如果你不想要打印每個命令。它關閉時避免了「++ set + x」輸出,並且看起來更乾淨。不過,對於只有一兩句話,bhassel使用subshel​​l的答案是最方便的。 – 2015-01-09 15:29:42

+0

這就是我要找的!不是'set + x',它會影響所有的命令,這太多了! – Hlung 2015-05-10 16:29:32

2

對於cshtcsh,你可以set verboseset echo(或者你甚至可以同時設置,但它可能會導致一些重複的大部分時間)。

verbose選項幾乎打印出您輸入的確切shell表達式。

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函數來回顯然後運行該命令。這對管道命令非常有用,否則這些命令只會顯示任何內容或僅顯示管道命令的初始部分。

沒有EVAL:

exe() { echo "\$ [email protected]" ; "[email protected]" ; } 
exe ls -F | grep *.txt 

輸出:

$ 
file.txt 

隨着EVAL:

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

,輸出

$ exe eval 'ls -F | grep *.txt' 
file.txt 
14

TLDPBash Guide for Beginners: Chapter 2. Writing and debugging scripts

2.3.1。在調試整個腳本

$ bash -x script1.sh 

...

現在有猛砸一個全面的調試器,可在SourceForge。這些調試功能在大多數現代版本的Bash中都可用,從3.x開始。

2.3.2。在調試腳本

set -x   # activate debugging from here 
w 
set +x   # stop debugging from here 

的一部分(S)...

表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 
1
$ cat exampleScript.sh 
#!/bin/bash 
name="karthik"; 
echo $name; 

bash -x exampleScript.sh 

輸出如下:

enter image description here

4

有人張貼以上:

#!/bin/bash 
#function to display commands 
exe() { echo "\$ [email protected]" ; "[email protected]" ; } 

和這個l ooks很有希望,但我不能爲了我的生活找出它的作用。我已經搜索了「\ $」和「$ @」的man bash頁面,並且絕對找不到

我明白正在創建一個名爲「exec()」的函數。我明白花括號標記了函數的開始和結束。我認爲我明白分號標誌着多行命令之間的「硬迴歸」,因此'{echo'\ $ $ @「; 「$ @」; }」成爲在本質:

{ 
echo "\$ [email protected]" 
"[email protected]" 

} 

任何一個可以給我一個簡要的解釋,或在哪裏可以找到這些信息,因爲很明顯我的谷歌福失敗了我? (set -x; [commands]; set + x「)方法對我來說是非常有效的,因爲這個方法對我來說非常適合,但我無法弄清楚如何將結果回顯到文件而不是屏幕,所以我試圖理解這種其他方法,希望我可以使用我對重定向/管道/ tee /等的相當差的理解來做同樣的事情東西)。

謝謝!

以後編輯:

與一些修修補補,我相信我想通了。這裏是我的等同的代碼,就是我需要:

SCRIPT_LOG="\home\buddy\logfile.txt" 
exe() { 
    params="[email protected]"      # Put all of the command-line into "params" 
    printf "%s\t$params" "$(date)" >> "$SCRIPT_LOG" # Print the command to the log file 
    $params       # Execute the command 
} 

exe rm -rf /Library/LaunchAgents/offendingfile 
exe rm -rf /Library/LaunchAgents/secondoffendingfile 

在LOGFILE.TXT看起來類似的結果:

Tue Jun 7 16:59:57 CDT 2016 rm -rf /Library/LaunchAgents/offendingfile 
Tue Jun 7 16:59:57 CDT 2016 rm -rf /Library/LaunchAgents/secondoffendingfile 

正是我需要的。謝謝!

+0

我相信我明白了。這裏是我的等同的代碼,就是我需要: EXE(){ PARAMS = 「$ @」 \t \t \t \t \t \t#把所有的命令行中的 「PARAMS」 的printf「%S \ T $ PARAMS 「 」$(日期)「 >> 」$ SCRIPT_LOG「 \t#打印命令將日誌文件 $ PARAMS \t \t \t \t \t \t \t#執行命令} \t EXE室射頻/庫/ LaunchAgents/COM .carbonite.launchd.carbonitealerts.plist \t exe rm -rf /Library/LaunchAgents/com.carbonite.launchd.carbonitestatus.plist – DebianFanatic 2016-06-07 21:53:07

+0

需要\ n在'printf'%s \ t $ params「」$(date)「中打破行」$ SCRIPT_LOG「' – user3762200 2017-08-16 15:22:07

3

您可以執行在調試模式下的bash腳本與-x選項
這將回顯所有的命令。

bash -x example_script.sh 

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


您也可以保存-x選項在腳本。只需在shebang中指定-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