Bash 找出所有管道命令的退出代码
如何在 Linux 或类 Unix 系统上使用 bash shell获取通过管道传输到另一个进程的进程的退出状态(例如 ' netstat -tulpn | grep nginx ')?
Shell 管道是一种无需任何临时文件即可将一个程序的输出连接到另一个程序的输入的方法。语法如下:
Shell 管道是一种无需任何临时文件即可将一个程序的输出连接到另一个程序的输入的方法。语法如下:
command1 | command2 | commandN ## OR ## command1 | filter_data_command > output ## OR ## get_data_command | verify_data_command | process_data_command | format_data_command > output.data.file
教程详细信息 | |
---|---|
难度等级 | 简单的 |
Root 权限 | 不 |
要求 | Linux 或 Unix 终端 |
类别 | Linux shell 脚本 |
操作系统兼容性 | BSD • Linux • macOS • Unix |
预计阅读时间 | 2 分钟 |
如何使用管道连接程序
两个命令之间使用竖线 ( |)。在此示例中,将 netstat 命令输出发送到grep 命令,即查明系统中 nginx 进程是否存在:
# netstat -tulpn | grep nginx
图01:查找管道命令的退出状态
如何获取通过管道传输到另一个进程的退出状态
获取所有管道命令的退出代码的语法如下:
command1 | command2 echo "${PIPESTATUS[@]}"
或者
command1 | command2 echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
PIPESTATUS 是一个数组变量,其中包含最近执行的前台管道中进程的退出状态值列表。尝试以下命令:
netstat -tulpn | grep nginx echo "${PIPESTATUS[@]}" true | true echo "The exit status of first command ${PIPESTATUS[0]}, and the second command ${PIPESTATUS[1]}" true | false echo "The exit status of first command ${PIPESTATUS[0]}, and the second command ${PIPESTATUS[1]}" false | false | true echo "The exit status of first command ${PIPESTATUS[0]}, second command ${PIPESTATUS[1]}, and third command ${PIPESTATUS[2]}"
图 02:使用 PIPESTATUS 数组获取管道每个元素的退出状态(点击放大)
综合起来
下面是一个示例脚本,它使用 ${PIPESTATUS[0]} 来找出 mysqldump 命令的退出状态,以便在屏幕上通知用户数据库备份状态:
#!/bin/bash ### Purpose: mysql.backup.sh : Backup database ### ### Author: Vivek Gite <https://www.example.com>, under GPL v2.x+ or above. ### ### Change as per your needs ### set -eo pipefail MUSER='USERNAME-here' MPASS='PASSWORD-here' MHOST='10.0.3.100' DEST="/nfs42/backups/mysql" NOWFORMAT="%m_%d_%Y_%H_%M_%S%P" MYSQL="/usr/bin/mysql" MYSQLDUMP="/usr/bin/mysqldump" MKDIR="/bin/mkdir" RM="/bin/rm" GZIP="/bin/gzip" DATE="/bin/date" SED="/bin/sed" # Failsafe? Create dir # [ ! -d "$DEST" ] && $MKDIR -p "$DEST" # Filter db names DBS="$($MYSQL -u $MUSER -h $MHOST -p$MPASS -Bse 'show databases')" DBS="$($SED -e 's/performance_schema//' -e 's/information_schema//' <<<$DBS)" # Okay, let us go for db in $DBS do tTime=$(date +"${NOWFORMAT}") FILE="$DEST/${db}.${tTime}.gz" $MYSQLDUMP -u $MUSER -h $MHOST -p$MPASS $db | $GZIP -9 > $FILE if [ ${PIPESTATUS[0]} -ne "0" ]; then echo "The command $MYSQLDUMP failed with error code ${PIPESTATUS[0]}." exit 1 else echo "Database $db dump successfully." fi done
关于 zsh 用户的说明
使用名为 pipestatus 的数组如下:
true | true echo "${pipestatus[1]} ${pipestatus[2]}"
输出:
0 0
结论 - 查找所有管道命令的退出代码
管道的退出状态是管道中最后一个命令的退出状态,除非还启用了 pipefail 选项。只需在 bash shell 脚本顶部添加以下内容:
set -eo pipefail
要在 Bash shell 中管道输出并捕获退出状态,请使用:
date | grep 2018 echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}" false | true echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
更多信息请参阅:
- 命令的退出状态
- Bourne Shell 退出状态示例
- GNU/bash 在线手册页在这里
- bash 手册页在这里