重击找出所有管道命令的退出代码

时间:2020-01-09 10:45:53  来源:igfitidea点击:

在使用bash shell的Linux或者类Unix系统上,如何获取通过管道传输到另一个进程的退出状态(例如,netstat -tulpn | grep nginx)?

Shell管道是一种将一个程序的输出连接到另一个程序的输入而无需任何临时文件的方法。语法为:

command1 | command2 | commandN

或者

command1 | filter_data_command> output

或者

get_data_command | verify_data_command | process_data_command | format_data_command> output.data.file

如何使用管道连接程序

在两个命令之间使用竖线(|)。在此示例中,将netstat命令输出发送到grep命令,即找出nginx进程是否在系统中退出:

# netstat -tulpn | grep nginx

如何获取通过管道传输到另一个的进程的退出状态

语法如下,以获取所有管道命令的退出代码:

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]}"

将所有东西组合一起

这是一个示例脚本,该脚本使用${PIPESTATUS [0]}找出mysqldump命令的退出状态,以便在屏幕上通知用户数据库备份状态:

#!/bin/bash
### Purpose: mysql.backup.sh : Backup database ###
### Author:  <https://www.theitroad.local>, 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 2016
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
false | true
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"