茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1670791 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
IMG_60D_00128.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

小企鵝開談 : [轉貼]How to debug a bash script?

發表者 討論內容
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼]How to debug a bash script?
How to debug a bash script?

Is there any way to debug a bash script? E.g something that prints a sort of execution log like "calling line 1", "calling line 2" etc.

--------------------------------------------------------------------------------
sh -x script [arg1 ...]
bash -x script [arg1 ...]

These give you a trace of what is being executed. (See also 'Clarification' near the bottom of the answer.)
Sometimes, you need to control the debugging within the script. In that case, as Cheeto reminded me, you can use:
set -x

This turns debugging on. You can then turn it off again with:
set +x

(You can find out the current tracing state by analyzing $-, the current flags, for x.)
Also, shells generally provide options '-n' for 'no execution' and '-v' for 'verbose' mode; you can use these in combination to see whether the shell thinks it could execute your script — occasionally useful if you have an unbalanced quote somewhere.

There is contention that the '-x' option in Bash is different from other shells (see the comments). The Bash Manual says:
-x
Print a trace of simple commands, for commands, case commands, select commands, and arithmetic for commands and their arguments or associated word lists after they are expanded and before they are executed. The value of the PS4 variable is expanded and the resultant value is printed before the command and its expanded arguments.
That much does not seem to indicate different behaviour at all. I don't see any other relevant references to '-x' in the manual. It does not describe differences in the startup sequence.
Clarification: On systems such as a typical Linux box, where '/bin/sh' is a symlink to '/bin/bash' (or wherever the Bash executable is found), the two command lines achieve the equivalent effect of running the script with execution trace on. On other systems (for example, Solaris, and some more modern variants of Linux), /bin/sh is not Bash, and the two command lines would give (slightly) different results. Most notably, '/bin/sh' would be confused by constructs in Bash that it does not recognize at all. (On Solaris, /bin/sh is a Bourne shell; on modern Linux, it is sometimes Dash — a smaller, more strictly POSIX-only shell.) When invoked by name like this, the 'shebang' line ('#!/bin/bash' vs '#!/bin/sh') at the start of the file has no effect on how the contents are interpreted.
The Bash manual has a section on Bash POSIX mode which, contrary to a long-standing but erroneous version of this answer (see also the comments below), does describe in extensive detail the difference between 'Bash invoked as sh' and 'Bash invoked as bash'.
When debugging a (Bash) shell script, it will be sensible and sane — necessary even — to use the shell named in the shebang line with the -x option. Otherwise, you may (will?) get different behaviour when debugging from when running the script.

--------------------------------------------------------------------------------

I've used the following methods to debug my script.
set -e
makes the script stop immediately if any external program returns a non-zero exit status. This is useful if your script attempts to handle all error cases and where a failure to do so should be trapped.
set -x
was mentioned above and is certainly the most useful of all the debugging methods.
set -n
might also be useful if you want to check your script for syntax errors.

--------------------------------------------------------------------------------

This answer is valid and useful: http://stackoverflow.com/a/951352
But, I find that the "standard" script debugging methods are inefficient, unintuitive, and hard to use. For those used to sophisticated GUI debuggers that put everything at your fingertips and make the job a breeze for easy problems (and possible for hard problems), these solutions aren't very satisfactory.
What I do is use a combination of DDD and bashdb. The former executes the latter, and the latter executes your script. This provides a multi-window UI with the ability to step through code in context and view variables, stack, etc., without the constant mental effort to maintain context in your head or keep re-listing the source.
There is guidance on setting that up here: http://ubuntuforums.org/showthread.php?t=660223

--------------------------------------------------------------------------------

You can also write "set -x" within the script.

--------------------------------------------------------------------------------

I found shellcheck utility and may be some folks find it interesting https://github.com/koalaman/shellcheck
A little example:
$ cat test.sh
ARRAY=("hello there" world)

for x in $ARRAY; do
  echo $x
done

$ shellcheck test.sh

In test.sh line 3:
for x in $ARRAY; do
         ^-- SC2128: Expanding an array without an index only gives the first element.

fix the bug, first try...
$ cat test.sh
ARRAY=("hello there" world)

for x in ${ARRAY[@]}; do
  echo $x
done

$ shellcheck test.sh

In test.sh line 3:
for x in ${ARRAY[@]}; do
         ^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.

Let's try again...
$ cat test.sh
ARRAY=("hello there" world)

for x in "${ARRAY[@]}"; do
  echo $x
done

$ shellcheck test.sh

find now!
It's just a small example.
shareimprove this answer

--------------------------------------------------------------------------------

I built a Bash debugger. Just give it a try. I hope it will help https://sourceforge.net/projects/bashdebugingbash

--------------------------------------------------------------------------------

I think you can try this Bash debugger: http://bashdb.sourceforge.net/.

--------------------------------------------------------------------------------

There's good amount of detail on logging for shell scripts via global varaibles of shell. We can emulate the similar kind of logging in shell script: http://cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html
The post has details on introdducing log levels like INFO , DEBUG, ERROR. Tracing details like script entry, script exit, function entry, function exit.
Sample log:


--------------------------------------------------------------------------------

Some trick to debug bash scripts:
Using set -[nvx]
In addition to
set -x

and
set +x

for stopping dump.
I would like to speak about set -v wich dump as smaller as less developped output.
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21

for arg in x v n nx nv nvx;do echo "- opts: $arg"
    bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
        set -$arg
        for i in {0..9};do
            echo $i
          done
        set +$arg
        echo Done.
eof
    sleep .02
  done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5

Dump variables or tracing on the fly
For testing some variables, I use sometime this:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args

for adding:
declare >&2 -p var1 var2

at line 18 and running resulting script (with args), without having to edit them.
of course, this could be used for adding set [+-][nvx]:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args

will add declare -p v1 v2 >&2 after line 18, set -x before line 22 and set +x before line 26.
little sample:
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
        seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8

Note: Care about $LINENO will be affected by on-the-fly modifications!
( To see resulting script whithout executing, simply drop bash <( and ) arg1 arg2 )
Step by step, execution time
Have a look at my answer about how to profile bash scripts

原文出處:shell - How to debug a bash script? - Stack Overflow
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼]shell script 的追蹤與 debug
12.6 shell script 的追蹤與 debug

scripts 在執行之前,最怕的就是出現語法錯誤的問題了!那麼我們如何 debug 呢?有沒有辦法不需要透過直接執行該 scripts 就可以來判斷是否有問題呢?呵呵!當然是有的!我們就直接以 bash 的相關參數來進行判斷吧!
[dmtsai@study ~]$ sh [-nvx] scripts.sh
選項與參數:
-n  :不要執行 script,僅查詢語法的問題;
-v  :再執行 sccript 前,先將 scripts 的內容輸出到螢幕上;
-x  :將使用到的 script 內容顯示到螢幕上,這是很有用的參數!

範例一:測試 dir_perm.sh 有無語法的問題?
[dmtsai@study ~]$ sh -n dir_perm.sh
# 若語法沒有問題,則不會顯示任何資訊!

範例二:將 show_animal.sh 的執行過程全部列出來~
[dmtsai@study ~]$ sh -x show_animal.sh
+ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/bin
+ export PATH
+ for animal in dog cat elephant
+ echo 'There are dogs.... '
There are dogs....
+ for animal in dog cat elephant
+ echo 'There are cats.... '
There are cats....
+ for animal in dog cat elephant
+ echo 'There are elephants.... '
There are elephants....

請注意,上面範例二中執行的結果並不會有顏色的顯示!鳥哥為了方便說明所以在 + 號之後的資料都加上顏色了! 在輸出的訊息中,在加號後面的資料其實都是指令串,由於 sh -x 的方式來將指令執行過程也顯示出來, 如此使用者可以判斷程式碼執行到哪一段時會出現相關的資訊!這個功能非常的棒!透過顯示完整的指令串, 你就能夠依據輸出的錯誤資訊來訂正你的腳本了!

熟悉 sh 的用法,將可以使你在管理 Linux 的過程中得心應手!至於在 Shell scripts 的學習方法上面,需要『多看、多模仿、並加以修改成自己的樣式!』 是最快的學習手段了!網路上有相當多的朋友在開發一些相當有用的 scripts ,若是你可以將對方的 scripts 拿來,並且改成適合自己主機的樣子!那麼學習的效果會是最快的呢!

另外,我們 Linux 系統本來就有很多的服務啟動腳本,如果你想要知道每個 script 所代表的功能是什麼? 可以直接以 vim 進入該 script 去查閱一下,通常立刻就知道該 script 的目的了。 舉例來說,我們之前一直提到的 /etc/init.d/netconsole ,這個 script 是幹嘛用的? 利用 vim 去查閱最前面的幾行字,他出現如下資訊:
# netconsole    This loads the netconsole module with the configured parameters.
# chkconfig: - 50 50
# description: Initializes network console logging
# config: /etc/sysconfig/netconsole

意思是說,這個腳本在設定網路終端機來應付登入的意思,且設定檔在 /etc/sysconfig/netconsole 設定內! 所以,你寫的腳本如果也能夠很清楚的交待,那就太棒了!

另外,本章所有的範例都可以在 http://linux.vbird.org/linux_basic/0340bashshell-scripts/scripts-20150717.tar.bz2 裡頭找到喔!加油~

原文出處:鳥哥的 Linux 私房菜 -- 第十二章、學習 Shell Scripts
前一個主題 | 下一個主題 | 頁首 | | |



Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|