shell编程基础(四): shell脚本语法之函数及调试
一、Shell脚本中的函数
和C语言类似,Shell中也有函数的概念,但是函数定义中没有返回值也没有参数列表。例如:
#! /bin/sh
fun(){ echo "Function fun is called";}
echo "-=start=-"
fun
echo "-=end=-"
注意函数体的左花括号'{'和后面的命令之间必须有空格或换行,如果将最后一条命令和右花括号'}'写在同一行,命令末尾必须有;号。
在定义fun()函数时并不执行函数体中的命令,就像定义变量一样,只是给fun这个名字一个定义,到后面调用fun函数的时候(注意Shell中的函数调用不写括号)才执行函数体中的命令。Shell脚本中的函数必须先定义后调用,一般把函数定义都写在脚本的前面,把函数调用和其它命令写在脚本的最后(类似C语言中的main函数,这才是整个脚本实际开始执行命令的地方)。
Shell函数没有参数列表并不表示不能传参数,事实上,函数就像是迷你脚本,调用函数时可以传任意个参数,在函数内同样是用$0、$1、$2等变量来提取参数,函数中的位置参数相当于函数的局部变量,改变这些变量并不会影响函数外面的$0、$1、$2等变量。函数中可以用return命令返回,如果return后面跟一个数字则表示函数的Exit Status。
下面这个脚本可以一次创建多个目录,各目录名通过命令行参数传入,脚本逐个测试各目录是否存在,如果目录不存在,首先打印信息然后试着创建该目录。
编辑脚本 [root@VM_0_5_centos test]# vi tfun.sh 查看脚本内容 [root@VM_0_5_centos test]# cat tfun.sh #! /bin/sh is_directory() { DIR_NAME=$1 if [ ! -d $DIR_NAME ]; then return 1 else return 0 fi } for DIR in "$@"; do if is_directory "$DIR" then : else echo "Directory $DIR doesn't exist. Creating it now..." mkdir $DIR > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "Can't create directory $DIR" exit 1 fi fi done 运行测试脚本 [root@VM_0_5_centos test]# sh tfun.sh aaa abb acc add Directory aaa doesn't exist. Creating it now... Directory abb doesn't exist. Creating it now... Directory acc doesn't exist. Creating it now... Directory add doesn't exist. Creating it now... 查看是否成功创建目录 [root@VM_0_5_centos test]# ll total 20 drwxr-xr-x 2 root root 4096 Jul 16 11:16 aaa drwxr-xr-x 2 root root 4096 Jul 16 11:16 abb drwxr-xr-x 2 root root 4096 Jul 16 11:16 acc drwxr-xr-x 2 root root 4096 Jul 16 11:16 add -rw-r--r-- 1 root root 340 Jul 16 11:15 tfun.sh
注意:is_directory()返回0表示真返回1表示假。mkdir $DIR > /dev/null 2>&1这条语句时因为直接使用mkdir $DIR或mkdir $DIR > /dev/null可能会出错,所以将可能出错的情况都重定向输出到/dev/null这个黑洞目录当中。
二、Shell脚本的调试方法
Shell提供了一些用于调试脚本的选项,如下所示:
-n
读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
-v
一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
-x
提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
使用这些选项有三种方法,一是在命令行提供参数
[root@VM_0_5_centos test]# sh -x tfun.sh a1 a2 a3
1 [root@VM_0_5_centos test]# sh -x tfun.sh a1 a2 a3 2 + for DIR in '"$@"' 3 + is_directory a1 4 + DIR_NAME=a1 5 + '[' '!' -d a1 ']' 6 + return 1 7 + set -x 8 + echo 'Directory a1 doesn'\''t exist. Creating it now...' 9 Directory a1 doesn't exist. Creating it now... 10 + mkdir a1 11 + '[' 0 -ne 0 ']' 12 + set +x 13 + echo 'Directory a2 doesn'\''t exist. Creating it now...' 14 Directory a2 doesn't exist. Creating it now... 15 + mkdir a2 16 + '[' 0 -ne 0 ']' 17 + set +x 18 + echo 'Directory a3 doesn'\''t exist. Creating it now...' 19 Directory a3 doesn't exist. Creating it now... 20 + mkdir a3 21 + '[' 0 -ne 0 ']' 22 + set +x
二是在脚本开头提供参数
#! /bin/sh -x
第三种方法是在脚本中用set命令启用或禁用参数
for DIR in "$@"; do if is_directory "$DIR" then : else set -x echo "Directory $DIR doesn't exist. Creating it now..." mkdir $DIR > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "Can't create directory $DIR" exit 1 fi set +x fi done
1 [root@VM_0_5_centos test]# sh tfun.sh b bb bbb 2 + echo 'Directory b doesn'\''t exist. Creating it now...' 3 Directory b doesn't exist. Creating it now... 4 + mkdir b 5 + '[' 0 -ne 0 ']' 6 + set +x 7 + echo 'Directory bb doesn'\''t exist. Creating it now...' 8 Directory bb doesn't exist. Creating it now... 9 + mkdir bb 10 + '[' 0 -ne 0 ']' 11 + set +x 12 + echo 'Directory bbb doesn'\''t exist. Creating it now...' 13 Directory bbb doesn't exist. Creating it now... 14 + mkdir bbb 15 + '[' 0 -ne 0 ']' 16 + set +x
set -x和set +x分别表示启用和禁用-x参数,这样可以只对脚本中的某一段进行跟踪调试。