Jus*_*tin 5 osx bash pipe io-redirection awk
我正在编写一个脚本(它将在 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
}
Run Code Online (Sandbox Code Playgroud)
awk 脚本有一些自定义值验证和退出代码。返回码 1、2 和 3 表示:
一个示例执行(隐藏 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
Run Code Online (Sandbox Code Playgroud)
您可以看到这${PIPESTATUS[@]}表明sudo和awk都成功了,这是预期的,因为我知道我有 sudo 访问权限,并且 awk 变量username已设置并具有日志条目。
现在,如果我们将 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
Run Code Online (Sandbox Code Playgroud)
完美的!
如果我执行了上面的命令,但忽略了定义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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,awk 脚本确实return 2,但现在由于某种原因,sudo/zgrep返回141,尽管命令的那部分根本没有改变......这就是我遇到的问题。
我什至尝试在不隐藏输出(STDOUT或STDERR)的情况下执行命令,结果是相同的,但没有显示错误:
$ sudo -n zgrep -h AuthenticationAllowed /var/log/accountpolicy.log* | awk -f ./parse-accountpoliocy.awk
$ echo ${PIPESTATUS[@]}
141 2
Run Code Online (Sandbox Code Playgroud)
awk脚本的退出代码如何更改存储在其中的sudo/zgrep命令的退出代码${PIPESTATUS[@]}?
$ echo $((141-128))
13
$ kill -l | grep 13
13 PIPE Broken pipe 29 INFO Information request
$
Run Code Online (Sandbox Code Playgroud)
所以 141 是 shell 如何将wait(2)包含PIPE信号的 16 位退出状态字(参见)转换为单个数字;在这种exit 3情况下不会发生这种情况,因为在通过管道传输的数据已经被处理awk(并且zgrep没有更多内容可以awk通过管道写入)之后会发生这种情况。该exit 2代替发生得很早,而zgrep仍然有它要管的数据awk,所以zgrep被困住了PIPE,当它试图写入awk已消失。