这篇博文是对Debugging Shell Scripts in Linux的翻译,希望能帮助到在Linux下写Shell脚本的童鞋。
大多数编程语言都有可用的调试工具,调试工具可用在执行程序或脚本的时候让你检查其内部是如何进行的。对于Shell脚本,我们没有任何可用的调试工具,唯一有的是通过命令行的标识(-n,-v和-x)来辅助我们调试脚本。
Disabling the Shell (-n option) 所谓的-n标识,是noexec的缩写,意为no execution。该标识使得Shell并不执行其中的脚本,而是仅仅检查语法错误。-n标识并不能确保Shell会执行其它任何检查,实际上它只会执行常规的语法检查。通过使用-n标识,Shell不执行脚本中的命令,所以你可以很安全地检查你的脚本中是否包含语法错误。
下面的例子给出了如何使用-n标识。 例如该脚本文件名称为debug_quotes.sh
代码语言:javascript复制#!/bin/bash
echo "USER=$USER
echo "HOME=$HOME"
echo "OSNAME=$OSNAME"
现在添加-n标识来运行该脚本:
代码语言:javascript复制$ sh -n debug_quotes
debug_quotes: 8: debug_quotes: Syntax error: Unterminated quoted string
从上面的输出可以看出有一个语法错误,缺少双引号。
Displaying the Scripts Commands ( -v option ) 所谓的-v标识使得Shell可以在详细输出模式(verbose mode)下运行。实际中,使用该标识可以在执行某行代码之前输出改行代码。这对于我们查找脚本错误是非常有帮助的。
下面我们创建一个Shell脚本,名称为“listusers.sh”,内容如下:
代码语言:javascript复制linuxtechi@localhost:~$ cat listusers.sh
#!/bin/bash
cut -d : -f1,5,7 /etc/passwd | grep -v sbin | grep sh | sort > /tmp/users.txt
awk -F':' ' { printf ( "%-12s %-40sn", $1, $2 ) } ' /tmp/users.txt
#Clean up the temporary file.
/bin/rm -f /tmp/users.txt
下面我们使用-v标识来执行这个脚本。
代码语言:javascript复制linuxtechi@localhost:~$ sh -v listusers.sh
#!/bin/bash
cut -d : -f1,5,7 /etc/passwd | grep -v sbin | grep sh | sort > /tmp/users.txt
awk -F':' ' { printf ( "%-12s %-40sn", $1, $2 ) } ' /tmp/users.txt
guest-k9ghtA Guest,,,
guest-kqEkQ8 Guest,,,
guest-llnzfx Guest,,,
pradeep pradeep,,,
mail admin Mail Admin,,,
#Clean up the temporary file.
/bin/rm -f /tmp/users.txt
linuxtechi@localhost:~$
在上面的输出中,脚本的原本输出和命令混在了一起。但是,通过使用-v标识,在脚本运行过程中,起码你可以知道当前脚本的执行状态。
Combining the -n & -v Options 我们也可以将多个标识进行组合(-n和-v)。通过这种组合可以得到更多好处,因为我们在查看脚本输出的过程中同时也检查了语法错误。
让我们再来看前面讨论过的脚本文件“debug_quotes.sh”。
代码语言:javascript复制linuxtechi@localhost:~$ sh -nv debug_quotes.sh
#!/bin/bash
#shows an error.
echo "USER=$USER
echo "HOME=$HOME"
echo "OSNAME=$OSNAME"
debug_quotes: 8: debug_quotes: Syntax error: Unterminated quoted string
linuxtechi@localhost:~$
Tracing Script Execution ( -x option ) 所谓的-x标识,是xtrace或者execution trace的缩写,��Shell执行完每一小步(每个子命令)后会输出每一步的结果。因此,我们可以看到变量和值和命令的结果。通常情况下,单独的-x命令可以帮助我追溯脚本的问题。
大多数时候,-x标识都会提供关于脚本的特别有用的信息,但是它也会导致大量的输出。下面的例子说明了如何在实践中使用。
代码语言:javascript复制linuxtechi@localhost:~$ sh -x listusers.sh
cut -d : -f1,5,7 /etc/passwd
grep -v sbin
sort
grep sh
awk -F: { printf ( "%-12s %-40sn", $1, $2 ) } /tmp/users.txt
guest-k9ghtA Guest,,,
guest-kqEkQ8 Guest,,,
guest-llnzfx Guest,,,
pradeep pradeep,,,
mail admin Mail Admin,,,
/bin/rm -f /tmp/users.txt
linuxtechi@localhost:~$
在上面的输出中,Shell在命令的前面添加了一个‘ ’的符号。