高级bash编程指南(十)
时间:2011-03-23 来源:xdzone
一 调试
1.设置选项
(1)bash -n scriptname 不会实际运行脚本,而只是检查标本的语法错误,
也可以在脚本中添加 set -n 或者set -o noexec
(2)bash -v scriptname在实际执行一个命令或者脚本前打印出这个命令或者脚本的内容,
也可以在脚本中添加set -v 或者set -o verbose
(3)bash -x scriptname 打印每个命令的执行结果,set -x or set -o xtrace
2.$LINENO和caller
(1)$LINENO 等同与vc中的 __LINE__
(2)caller
#!/bin/bash
func()
{
caller 0
}
func
exit 0
把caller放在函数中,可以输出这个函数在哪一行被调用的,以及是在哪个函数中调用的
以及该脚本被调用时的命令。
eg: 10 main ./test.sh
3.像C语言中写一个assert函数
#!/bin/bash
assert()
{
E_ARGS=98
E_ASSERT_FSILED=99
if [ -z "$2" ];then
return $E_ARGS
fi
lineno=$2
if [ ! $1 ];then
echo "Assertion failed:File \"$0\",line $lineno,\"$1\""
exit $E_ASSERT_FAILED
fi
}
a=5
b=4
assert "$a -lt $b" $LINENO
#other command
echo "hello shell"
exit 0
4.trap 捕捉信号
trap 'command' SIG
trap 'echo ctrl-c' 2
trap 2 #恢复
trap 'command' DEBUG #DEBUG 每执行一行脚本执行一次command
二 Bash选项
用来改变shell或脚本行为的机制
bash [-optiion缩写] or bash -o [option名称]
缩写 | 名称 | 作用 |
---|---|---|
-C | noclobber | 防止重定向时覆盖文件 (此作用会被>|覆盖) |
-D | (none) | 列出双引号引起的含有$前缀的字符串,但不执行脚本中的命令 |
-a | allexport | 导出所有定义的变量到环境变量中 |
-b | notify | 当后台任务终止时给出通知 (在脚本中用的不多) |
-c ... | (none) | 从...读命令 |
-e | errexit | 脚本发生第一个错误时就中止脚本运行,即当一个命令返回非零值时退出脚本 (除了until 或 while loops, if-tests, list constructs) |
-f | noglob | 文件名替换停用(指像*这样的符号不能替换为文件名了) |
-i | interactive | 使脚本以交互式方式运行 |
-n | noexec | 从脚本里读命令但不执行它们(语法检查) |
-o Option-Name | (none) | 调用Option-Name 选项 |
-o posix | POSIX | 更改Bash或脚本的行为,使之符合POSIX标准. |
-p | privileged | 脚本作为"suid"程序来运行 (小心!) |
-r | restricted | 脚本在受限模式中运行 (参考第21章). |
-s | stdin | 从标准输入读命令 |
-t | (none) | 第一个命令后就退出 |
-u | nounset | 当使用一个未定义的变量时产生一个错误信息,并强制退出脚本。 |
-v | verbose | 执行命令之前打印命令到标准输出 |
-x | xtrace | 与-v相似, 但打印完整的命令 |
- | (none) | 选项列表结束的标志. 后面的参数是位置参数(positional parameters). |
-- | (none) | 释放位置参数. 如果参数列表被指定了(-- arg1 arg2), 则位置参数被依次设置为参数列表中的值.sa |
三 小技巧
1.脚本可以像内嵌到另一个shell脚本的普通命令一样调用,如Tcl或wish脚本,甚至Makefile.它们可以作为外部shell命令用C语言的system()函数调用。
2.把你经常用的自定义的变量和函数放在文件中,当需要使用的时候,在脚本中使用点号.或source命令来包含这些“库文件”的一个或多个。
#mybashlib.sh
ROOT_ID=0
E_NOROOT=101
Check_is_root()
{
if [ "$UID" -ne "$ROOT_ID" ];then
echo "Must be root to run this script."
exit $E_NOROOT
fi
}
#test.sh
#!/bin/bash
. /home/zone/mybashlib.sh #包含”库文件“,其实该句相当与执行该脚本文件
#所以”库文件“中最好不要存在一些执行性的语句,而仅仅是定义一些函数和变量。
Check_is_root #调用函数
exit 0
3.注释代码块
(1)here文档
: <<COMMENTBLOCK
echo "This line will not echo"
=======================
echo "hello world"
=======================
COMMENTBLOCK
(2)if-test结构
#!/bin/bash
COMMENT_BLOCK=
if [ $COMMENT__BLOCK ];then
================
echo "comment"
================
fi
#通过给变量 COMMENT_BLOCK来控制注释开关
4.函数返回值给脚本,一个方法就是return num,但是num必须时0~255;另一种方法
就是让函数写值到标准输出,这种方法不仅可以返回整数,字符串,而且可以返回
多个值。
eg
#!/bin/bash
sum_and_product()
{
echo $(($1+$2)) $(($1*$2))
}
sumproduct=$(sum_and_product 10 100)
sum=$(echo "$sumproduct"|awk '{print $1}')
product=$(echo "$sumproduct"|awk '{print $2}')
exit 0
5.传递数组参数给函数,从函数返回数组
arg=$(echo "${arr[@]}"),然后把便另arg传递给函数
返回数组的时候可以用同样的方法。