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