bash 数组 $PIPESTATUS 出现问题

bash 数组 $PIPESTATUS 出现问题

我正在编写一个脚本(将在 OSX 上运行,可能不会运行其他任何东西),它基本上只是解析日志/var/log/accountpolicy.log*以获取身份验证时间/计数。初始命令是zgrep通过 执行的sudo,该命令通过管道传输到awk,执行 awk 脚本。运行命令后,我用来${PIPESTATUS[@]}确定是否有任何失败,如果失败,是哪一部分。

这是当前状态的 awk 脚本:

#! /usr/local/bin/awk -f

BEGIN {
  return_code = 0
  if ( length( username ) == 0 ){
    return_code = 2
    exit return_code
  }

  rows = 0
}
{ 
  if ( $8 != sprintf("\"%s\",", username ) ) next

  rows = rows+1
  print $0
} 
END {
  if ( return_code > 0 ) exit return_code
  if ( rows == 0 ) exit 3
}

awk 脚本有一些自定义值验证和退出代码。返回码 1、2 和 3 的含义是:

  1. awk 失败(由于与 awk 相关的某种原因)
  2. 未指定 awk 解析的用户名
  3. 已指定用户名,但未找到任何值

测试#1(工作正常)

一个示例执行(隐藏 awk 脚本的输出,因为这个问题与返回代码具体相关):

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -v username="${USER}" -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
0 0

您可以看到${PIPESTATUS[@]}表明和都sudo成功awk了,这是预期的,因为我知道我有 sudo 访问权限,并且 awk 变量username已设置并具有日志条目。

测试#2(工作正常)

现在,如果我们将 awk 变量更改username为一个帐户不存在,那么 awk 脚本应该退出,返回码为3

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -v username="fakeuser" -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
0 3

完美的!

测试#3(问题..)

如果我执行上面的命令,但忽略定义usernameawk 变量,那么 awk 脚本应该返回码为 2 退出

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* 2>/dev/null | awk -f ./parse-accountpoliocy.awk &>/dev/null
$ echo ${PIPESTATUS[@]}
141 2

如您所见,awk 脚本return 2,但现在由于某种原因,sudo/zgrep返回141,尽管命令的这一部分根本没有改变......这就是我遇到的问题。

我什至尝试执行该命令而不隐藏输出(任一标准输出或者标准错误错误率),结果是一样的,但是没有报错:

$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log*  | awk -f ./parse-accountpoliocy.awk
$ echo ${PIPESTATUS[@]}
141 2

问题

脚本的退出代码如何更改存储在其中的/命令awk的退出代码?sudozgrep${PIPESTATUS[@]}


环境信息

  • OSx 版本:10.11.6 (El Capitan)
  • 重击版本:4.4.12
  • AWK 版本:GNU Awk 4.1.4

答案1

$ echo $((141-128))
13
$ kill -l | grep 13
13   PIPE Broken pipe                   29   INFO Information request
$ 

因此,141 是 shell 将wait(2)包含信号的 16 位退出状态字(请参阅 参考资料)整合PIPE为单个数字的方式;这种情况不会发生,exit 3因为这种情况发生了正在通过管道传输的数据已完成处理awk(并且没有更多内容可通过管道zgrep写入)。相反,awkexit 2发生得很早,同时zgrep仍然有想要通过管道传输到的数据awk,因此当它尝试写入已消失的数据时zgrep,会受到 a 的打击。PIPEawk

相关内容