help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Is there a way to make unamed pipe nonexist upon error?


From: Stephane Chazelas
Subject: Re: [Help-bash] Is there a way to make unamed pipe nonexist upon error?
Date: Thu, 26 Sep 2019 08:01:33 +0100
User-agent: NeoMutt/20171215

2019-09-25 22:39:17 -0500, Peng Yu:
[...]
> awk does not know there is not a file called nosuchfile.txt because
> the unnamed pipe looks OK. Is there a way to make the pipe
> unavailable, so that awk knows there is some error with the file `f`?
> Thanks.
> 
> $ awk -v f=<(cat nosuchfile.txt) -e 'BEGIN { r = getline < f ; print r }'
> cat: nosuchfile.txt: No such file or directory
> 0
[...]

No, there is not. A pipe is an IPC mechanism. Above cat and awk
are started concurrently, cat eventually exits with a non-zero
exit status, but that makes no difference to the pipe (which was
created by the shell). Upon termination of cat, with an error or
not, the writing end of the pipe is closed which means EOF is
seen on the reading end.

What you can do is something like:

gawk -v f=<(cat nosuchfile.txt || echo FAILED) '
  BEGIN {
    RS="^$"
    getline content < f
    if (content ~ /FAILED/) {
      print "failed" > "/dev/stderr"
      exit(1)
    }
  }'

In theory, instead of echo FAILED, you could add code that tries
to identify the process(es) that are at the other end of the
pipe and kill the one that is running awk if any. On Linux and
with recent versions of lsof, that could be done with something
like:

gawk -v f=<(
  cat nosuchfile || {
    re=$'\nnpipe[^\n]*[ ,]([[:digit:]]+),gawk,[[:digit:]]+r'
    [[ ! $(lsof -Fn -ad3 -E -p "$BASHPID") =~ $re ]] ||
      kill "${BASH_REMATCH[1]}"
  } 3>&1) '
  BEGIN {
    RS="^$"
    r = getline content < f
    print r, content
  }'

but that sounds a bit overkill.

awk can run the command and get its output through a pipe by
itself, and in that case, it can retrieve its exit status, so
that sounds like a better approach if you want awk to know that
the command failed:

CMD='cat nosuchfile' gawk '
  BEGIN {
    RS="^$"
    r = ENVIRON["CMD"] | getline output
    status = close(ENVIRON["CMD"])
    print r, status, output
  }'

Here, with my version of gawk, I get:

cat: nosuchfile: No such file or directory
0 256

Where 256 is the exit status as returned by pclose()/waitpid(),
which is rc<<8. IMMV, but if that number is non-zero, the
command failed (either returned with a non-zero exit code or was
killed).

-- 
Stephane




reply via email to

[Prev in Thread] Current Thread [Next in Thread]