4

I was trying run a few commands using getline() function of GNU awk and print the error number (errno) value returned. But for simple failure cases of non existent directory/file the variable doesn't seem to be populated.

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

When the above puts out the error string from ls, the print statement does not produce a valid error number. I've also tried from the man page to use PROCINFO["errno"] and PROCINFO["ERRNO"] which didn't work. I also tried printing it before closing the file descriptor which also didn't work. Is it wrong to expect ENOENT in this case?

6

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
  • So the cmd|getline result not a proper way to catch the error number? How would it need to be used if I want to catch the error number, which I think in this case should be 2? (ENOENT) – Inian Mar 21 at 9:37
  • @Inian Use system instead. In this case, you just have to check getline returns 0 or not. getline encounter EOF means ls can not produce output. – cuonglm Mar 21 at 9:41
  • I was looking at gnu.org/software/gawk/manual/html_node/Auto_002dset.html under ERRNO. May be I missed a point if they were referring it applies only when used system() – Inian Mar 21 at 9:51
  • @Inian See my edited version – cuonglm Mar 21 at 9:53
  • 2
    @Inian maybe your gawk version does not honor POSIXLY_CORRECT, you may try awk --posix. ERRNO variable is set when one of your awk function failed to run. It has nothing to do with cmd. – cuonglm Mar 21 at 10:15
4

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;
    }
}'
  • Thanks! I see 512 as the code returned from ls. But why is it not throwing ENOENT (2) which is the error number corresponding to 'No such file or directory'? – Inian Mar 21 at 9:35
  • Can you give link to document indicates that close(cmd) returns the exit code of command? If that's true, then that should be exit status (512), not exit code (2) – cuonglm Mar 21 at 9:40
  • GNU awk: gnu.org/software/gawk/manual/html_node/… The return code is a mess, but 0..255 are exit codes, 256..511 signal codes, 512.. signal codes if a core dump happened. – Uwe Ohse Mar 21 at 9:43
  • @inian: the ls exit code is not an errno, it is just a state code. And on my system i get exit code 2. – Uwe Ohse Mar 21 at 9:50
  • @UweOhse No, I found by looking at GNU awk source code, it's the exit status when GNU awk not in posix mode, see my edited answer. – cuonglm Mar 21 at 9:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.