Shell 函数入门:定义、传参与返回值
为什么需要 Shell 函数
写 Shell 脚本时,经常会遇到同一段命令反复出现:检查服务状态、打一条带时间的日志、备份某个目录。复制粘贴三次还能忍,第五次就该收进函数里了。函数把一段命令打包成一个名字,以后只写名字就能调用,改逻辑也只改一处。
两种定义写法
最常见的写法是 name() { ...; },function 关键字可加可不加:
say_hello() {
echo "hello, $1"
}
function say_hello {
echo "hello, $1"
}
两种写法完全等价,用第一种的人更多。注意:函数必须先定义、后调用,脚本是自上而下执行的,在定义之前调用会报 command not found。
传参:位置参数
调用函数时跟在名字后面的就是参数,函数体内用位置参数接收:$1 是第一个参数,$2 是第二个,$@ 是全部参数,$# 是参数个数。注意这里的 $1 是函数的参数,不是脚本的参数,两者互不干扰:
backup() {
echo "正在备份 $1 到 $2"
cp -r "$1" "$2"
}
backup /etc/nginx /tmp/nginx.bak
参数一定要加双引号,否则带空格的路径会被拆成两个参数,这是新手最常踩的坑。
返回值:两种通道
函数有两种方式把结果交出来。第一种是退出状态码:return 0 表示成功,非零表示失败,调用方用 $? 读取。注意状态码只能是 0 到 255,return 300 会被截断:
is_root() {
[ "$(id -u)" -eq 0 ]
}
if is_root; then
echo "当前是 root"
fi
第二种是标准输出:函数里 echo 的内容,调用方用命令替换 $(...) 接住,适合返回字符串:
today() {
date +%Y-%m-%d
}
echo "今天是 $(today)"
局部变量:别污染全局
函数里赋值的变量默认是全局的,函数外也能看到,容易互相踩。养成习惯:函数内部一律用 local 声明:
count_files() {
local dir=$1
local n=$(ls "$dir" | wc -l)
echo "$n"
}
local 只能在函数体内用,写在函数外会报错。
一个顺手的例子:带时间戳的日志函数
log() {
echo "[$(date '+%H:%M:%S')] $*"
}
log "开始部署"
log "部署完成"
脚本里所有关键步骤都走 log,出了问题按时间翻日志,一眼就能定位到哪一步卡住了。
小结
函数三件事:定义用 name() { },传参用 $1、$2、$@,返回结果用状态码或 echo。先把重复三遍以上的命令收进函数,再顺手加个 log 函数,你的脚本会立刻清爽很多。
- 点赞
- 收藏
- 关注作者
评论(0)