1.11 函数和参数
和其他脚本语言一样,Bash同样支持函数。让我们看看它是如何定义和使用函数的。
1.11.1 实战演练
定义函数:
function fname()
{
statements;
}
或者
fname()
{
statements;
}
只需要使用函数名就可以调用某个函数:
- $ fname ; # 执行函数
参数可以传递给函数,并由脚本进行访问:
- fname arg1 arg2 ; # 传递参数
以下是函数fname
的定义。在函数fname
中,包含了各种访问函数参数的方法。
fname()
{
echo $1, $2; # 访问参数1和参数2
echo "$@"; # 以列表的方式一次性打印所有参数
echo "$*"; # 类似于$@,但是参数被作为单个实体
return 0; # 返回值
}
类似地,参数可以传递给脚本并通过script:$0
(脚本名)访问。
$1
是第一个参数。$2
是第二个参数。$n
是第n个参数。"$@"
被扩展成"$1"
"$2"
"$3"
等。"$*"
被扩展成"$1c$2c$3"
,其中c
是IFS的第一个字符。"$@"
用得最多。由于"$*"
将所有的参数当做单个字符串,因此它很少被使用。
1.11.2 补充内容
让我们再研究Bash函数的一些技巧。
- 递归函数
在Bash中,函数同样支持递归(可以调用自身的函数)。例如,F() { echo $1; F hello; sleep 1; }
。
Fork炸弹
- :(){ :|:& };:
这个递归函数能够调用自身,不断地生成新的进程,最终造成拒绝服务攻击。函数调用前的
&
将子进程放入后台。这段危险的代码会分支出大量的进程,因而被称为Fork炸弹。上面这段代码要理解起来可不容易。请参阅维基百科http://en.wikipedia.org/wiki/Fork_bomb,那里列出了有关Fork炸弹的细节以及更详细的解释。
可以通过修改配置文件/etc/security/limits.conf来限制可生成的最大进程数来避开这枚炸弹。
- 导出函数
函数也能像环境变量一样用export
导出,如此一来,函数的作用域就可以扩展到子进程中,如下:
- export -f fname
- 读取命令返回值(状态)
我们可以按照下面的方式获取命令或函数的返回值:
- cmd;
- echo $?;
$?
会给出命令cmd
的返回值。
返回值被称为退出状态。它可用于分析命令执行成功与否。如果命令成功退出,那么退出状态为0,否则为非0。
我们可以按照下面的方法检测某个命令是否成功结束:
#!/bin/bash
#文件名: success_test.sh
CMD="command" # command指代你要检测退出状态的目标命令
status
$CMD
if [ $? -eq 0 ];
then
echo "$CMD executed successfully"
else
echo "$CMD terminated unsuccessfully"
fi
- 向命令传递参数
命令的参数能够以不同的格式进行传递。假设-p
、-v
是可用选项,-k NO
是另一个可以接受数字的选项,同时该命令还接受一个文件名作为参数,那么,它有如下几种执行方式:
$ command -p -v -k 1 file
或者
$ command -pv -k 1 file
或者
$ command -vpk 1 file
或者
$ command file -pvk 1