命令失败时未设置 GNU awk ERRNO

命令失败时未设置 GNU awk ERRNO

getline()我尝试使用GNU 函数运行一些命令awk并打印返回的错误号 ( errno) 值。但对于不存在的目录/文件的简单故障情况,变量似乎没有被填充。

awk 'BEGIN {
        cmd = "ls -lrth /non/existing/path"
        while ( ( cmd | getline result ) > 0 ) {
            print result
        }
        close(cmd); print ENVIRON["ERRNO"]
}'

当上面从 中输出错误字符串时ls,该print语句不会产生有效的错误号。我也尝试过从手册页使用PROCINFO["errno"]PROCINFO["ERRNO"]哪个不起作用。我还尝试在关闭文件描述符之前打印它,但这也不起作用。ENOENT在这种情况下,期望是错误的吗?

答案1

您无法使用 获取错误号getline。在您的命令中,输出来自ls,而不是print result

在形式 中cmd | getline resultcmd运行,然后其输出通过管道传输到getline1如果有输出,则返回;0如果失败,则返回 EOF -1。问题是失败是由于运行getline本身,而不是cmd.例子:

awk 'BEGIN {
while ( ( getline result < "/etc/shadow") > 0 ) {
            print result
        }
        print "XXX: ", ERRNO
}'
XXX:  Permission denied

您将看到/etc/shadow无法读取,因此getline无法运行并报告变量错误ERRNO


cmd请注意,如果不在 posix 模式下,GNU awk 将返回状态,因此您可以执行以下操作:

awk 'BEGIN {
    cmd = "ls -lrth /non/existing/path"
    while ( ( cmd | getline result ) > 0 ) {
        print result
    }
    status=close(cmd);
    if (status != 0) {
        code=and(rshift(status, 8),0xFF)
        printf("Exit status: %d, exit code: %d\n", status, code)
    }
}'
ls: cannot access '/non/existing/path': No such file or directory
Exit status: 512, exit code: 2

在 POSIX 模式下,您不会获得退出状态:

POSXILY_CORRECT=1 awk 'BEGIN {
    cmd = "ls -lrth /non/existing/path"
    while ( ( cmd | getline result ) > 0 ) {
        print result
    }
    status=close(cmd);
    if (status != 0) {
        code=and(rshift(status, 8),0xFF)
        printf("Exit status: %d, exit code: %d\n", status, code)
    }
}'
ls: cannot access '/non/existing/path': No such file or directory

答案2

ERRNO 只能由 gawk 设置(GNU awk仅有的) 如果 getline 或 close 失败,但它成功读取 ls 的(空!)输出。该输出为空,因为 ls 在标准错误通道上给出错误消息(“ls:无法访问...”),不向标准输出写入任何内容,并且存在错误代码。

使用 GNU awk,您可以获得命令的退出状态,如下所示:

exitstatus=close(cmd)
if (exitstatus) {
    # do something
}

如果您需要命令的错误消息,那么您必须将其标准错误通道重定向到某个文件,然后阅读:

awk 'BEGIN {
    cmd = "ls -lrth /non/existing/path 2>standard-error.txt"
    while ( ( cmd | getline result ) > 0 ) {
        print result
    }
    es=close(cmd);
    if (es) {
        getline errstring < "standard-error.txt"
        print "exitstatus "es" error message "errstring;
    }
}'

相关内容