shell脚本中使用return和exit的方法
作者:西京刀客
shell脚本之如使用return和exit
return和exit各有用途,合理使用可以使shell编程更规范可控。
一、exit和return基础
1、return是一个关键字; exit是一个函数。
2、return是编程语言级别,它表示调用堆栈的返回;exit是系统调用级别,它表示了一个进程的结束。
3、return是函数的退出(返回);exit是进程的退出。
exit 0
正常运行程序并退出程序。使用echo $?返回0,也就是说调用环境认为你的程序执行正常。
exit 1
非正常运行导致退出程序,也可以是其他数字,例如exit -1。系统程序对于程序运行错误是有约定含义的,不为 0 就表示程序运行出错。调用环境根据这个返回值,判断你的程序运行是否正常。
return 0用于函数中,表示函数执行成功并返回 0;而exit 0 则表示当前程序执行成功并且直接退出当前执行脚本或程序。
return -1 表示函数执行失败返回错误;exit 1 (或大于 1)表示程序执行失败并退出程序。
总结: exit用于退出整个shell脚本进程。
EXIT退出指令举例
"exit"命令是终止Bash shell脚本的最常见方法之一。它允许脚本在执行过程中的任何时候退出,并且可以使用可选的退出代码来表示脚本终止的原因。
# 检查一个文件是否存在 if [ -f "myfile.txt" ]; then echo "The file exists" exit 0 # 成功的退出 else echo "The file does not exist" exit 1 # 异常的退出并附带说明 fi
在这个例子中,脚本使用“-f”测试运算符检查一个名为“myfile.txt”的文件是否存在。如果文件存在,脚本会向控制台打印一条消息,并使用“exit”命令以成功代码0退出。如果文件不存在,脚本会打印不同的消息,并使用错误代码1退出。
“exit”命令还可以用于处理脚本执行过程中的错误或意外情况。例如,假设一个脚本需要访问可能不可用的资源,如网络服务或数据库。在这种情况下,脚本可以使用“exit”命令以错误消息和适当的退出代码优雅地终止。
在函数中使用return语句退出举例
#!/bin/bash # 定义一个函数并返回数字之和 function add_numbers { local num1=$1 local num2=$2 local sum=$((num1 + num2)) return $sum } # 调用函数并打印结果 read_file "myfile.txt" # 调用函数并打印结果 add_numbers 3 71 result=$? echo "3 + 71 = $result"
在这个例子中,脚本定义了一个名为“add_numbers”的函数,它接受两个参数并返回它们的总和。在函数内部,使用“return”命令以总和作为返回值退出。
**“return”命令也可以用于处理函数内部的错误或意外情况。**例如,假设一个函数需要从一个文件中读取数据,但是该文件不存在。在这种情况下,函数可以使用“return”命令以错误代码和错误消息退出。
#!/bin/bash # 定义一个函数读取文件 function read_file { local file=$1 if [ ! -f "$file" ]; then echo "Error: File $file not found" return 1 fi cat $file }
如果文件不存在,函数将打印一个错误消息并返回错误代码1,该代码可以由调用脚本或进程用于相应地处理错误。
**在函数内使用“return”命令是一个很好的方式,可以正确退出函数并将其结果传达给脚本的其他部分或调用进程。**通过使用适当的返回值和错误代码,脚本可以处理意外情况,并提高其整体稳健性和可靠性。
二、最佳实践
- 函数必须使用return退出,不能用exit。
- 脚本主体逻辑使用return设置退出码,最后用exit退出脚本。
- 如果需要精确控制退出码,脚本中的各处逻辑都建议用return。
- 发生不可处理的错误时,可以直接用exit终止脚本。
三、子脚本返回非零状态码时导致主控脚本退出中断的问题
问题描述
主控脚本A,循环调用子脚本B、C,执行B子脚本exit,发现主控脚本A循环中断了,C子脚本没有调用
[重要]问题分析
开始以为:exit 会导致整个脚本进程结束,主控制脚本循环也会被中断。测试发现子脚本 exit非零,会导致主控脚本也直接退出
其实最后发现,是我主控日志打印,根据子脚本的 $? 结果,非0时自己exit 的,并不是因为子脚本非0 exit,主控就一定退出!!! 是一场乌龙~
结论:子脚本的exit不会直接导致主脚本退出,主程序要自行处理$?并决定下一步操作。
不过可以这里总结出如下2个比较有用的shell实践技巧:
- 善用exit $?
- 使用 sh 调子脚本
使用函数+return 方式返回状态码,最后 exit $? 方式退出脚本
完整示例demo:
start_mongodb(){ $MONGODB_BIN_DIR/mongod -f $MONGO_CONF if [ $? -eq 0 ]; then echo "MongoDB started successfully" return 0 else echo "Failed to start MongoDB" return 1 fi } stop_mongodb(){ $MONGODB_BIN_DIR/mongod -f $MONGO_CONF --shutdown if [ $? -eq 0 ]; then echo "MongoDB stopped successfully" return 0 else echo "Failed to stop MongoDB" return 1 fi } status(){ if [ -f $MONGODB_PIDFILE ]; then echo "MongoDB is running, PID: $(cat $MONGODB_PIDFILE)" return 0 else echo "MongoDB is stopped" return 1 fi } function control_mongodb(){ case $1 in start) start_mongodb ;; stop) stop_mongodb ;; restart) stop_mongodb start_mongodb ;; status) status ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 esac return $? } # 调用函数 control_mongodb $1 exit $?
在Linux shell脚本中,exit $? 表示使用上一个命令的退出状态码来退出当前shell脚本。$? 是一个特殊变量,它保存了上一个执行的命令或者函数的退出状态码。退出状态码0表示成功执行,非0通常表示失败或错误。exit $? 的具体作用是:
- $? 获取上一个命令的退出码
- exit 使脚本退出
- 将上一个命令的退出码作为脚本的最终退出码
使用 sh 调子脚本,需要注意事项
使用 sh 调子脚本,通常有下面的几种使用场景:
强制子脚本在一个干净的环境中运行。
sh
会启动一个新的shell实例,不会继承当前shell的任何自定义设置、变量等,可以提供一个干净隔离的运行环境。- 为子脚本设置特定的shell。直接调用子脚本时,使用当前shell(通常是bash),但有时需要指定为sh、csh等其他shell。
- 在脚本中改变目录时,调用子脚本使用相对路径。
sh
重置了工作目录,使相对路径生效。- 当子脚本需要另一个版本的shell时。直接调用继承当前shell,但 sh 可以指定所需的shell。
- 在升级系统shell时,保证子脚本向后兼容。直接调用使用新shell可能出错,但 sh 调用可保持原有的shell。
- 出于安全考虑,不信任子脚本,使用 sh 加沙箱隔离。
- 在守护进程中调用脚本,需要一个干净可预测的新shell环境。一些老的脚本依赖 sh 调用,直接转换会破坏原有行为。
总之,使用 sh 调用主要是为了精细控制子脚本的执行环境,符合特定的兼容性要求等。但通常需要时,直接调用更简单。
其实一般情况下,不推荐使用 sh,因为有时通过sh 调子脚本会有问题,例如:sh 执行脚本时, kill 命令出现了非法选项的错误
dash 和 bash 在处理 kill 命令选项上有一些细微区别。dash 不支持不带参数的 kill 命令,也不支持kill -s 信号的方式,需要直接写信号名。所以在 bash 下可以正常执行:
kill -SIGTERM pid kill -s TERM pid
但在 dash 下,需要写成:
kill -TERM pid
你的脚本本身没有问题,但当通过 sh 调用时,使用了 dash 的限制导致了错误。可以修改为直接调用脚本,不使用 sh:
./nginx_ctrl.sh stop
或者在脚本中用 kill -TERM 替代 kill -s TERM。这种 shell 的差异导致的错误可以引起注意,如果兼容 sh/dash 也需要调整下参数格式。
你可以通过以下几种方法来判断系统默认的 sh 是什么 shell:
1.直接运行 sh,看看默认进入的是什么 shell:
$ sh $ echo $SHELL /bin/dash
如果打印出来是 /bin/dash,那么默认就是 dash。
2. 查看 /bin/sh 的符号链接所指向的文件:
$ ls -l /bin/sh lrwxrwxrwx 1 root root 4 Mar 15 2020 /bin/sh -> dash
如果是指向 dash 就表示默认是 dash。
Ubuntu 和 Debian 默认就是 dash。
到此这篇关于shell脚本之如使用return和exit的文章就介绍到这了,更多相关shell使用return和exit内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!