GNU awk ERRNO not set on command failure

You can not get the error number using getline. In your command, the output is from ls, not print result.

In form cmd | getline result, cmd is run, then its output is piped to getline. It returns 1 if got output, 0 if EOF, -1 on failure. The problem is that failure is from running getline itself, not the return code of cmd. Example:

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

You will see that /etc/shadow can not be read, so getline fails to run and reports the error in ERRNO variable.


Note that GNU awk will return the cmd status if not in posix mode, so you can do:

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

In POSIX mode, You won't get the exit status:

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

ERRNO will only be set by gawk (GNU awk only) if the getline or close fails, but it succeeds in reading the (empty!) output of ls. That output is empty, because ls gives an error message ("ls: cannot access ...") on the standard error channel, writes nothing to the standard output, and exists with an error code.

With GNU awk you can get the exit status of the command like that:

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

If you need the error message of the command, then you haveto redirect its standard error channell to some file, and read that:

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;
    }
}'

Tags:

Awk

Gawk