1

I wonder why some similar bash commands behave the way they do.

I have a bash script foo:

#!/usr/bin/env bash

while true
do
    echo "reading"
    read data
    echo $data
    echo "stderr msg" >&2
    sleep 1
done

It's an infinite loop which reads one line at a time from stdin and outputs that same line. I also have a bash script bar:

#!/usr/bin/env bash

./foo &

The following commands were run in bash (v. 4.4.19) in a terminal on Ubuntu 18.04 (let's assume the scripts reside in the working directory):

  1. ./foo &

    • Stops when it tries to read from stdin, in accordance with this answer.

    • Killed when controlling terminal is killed, as expected.

  2. (./foo &)

    • Appears to be automagically continuously fed with new input from stdin. Shouldn't it too stop when attempting to read from stdin? Whatever it's getting it doesn't show when echoed, thus I'm guessing it's EOF characters.

    • Continues running even after the controlling terminal is killed. Looking at the output of ps, the controlling terminal changes from pts/x to ?. How did this happen without the use of either disown or nohup? (However, after killing the originally controlling terminal, it yields a "write error: Input/output error" on every write, which I suppose is because its stdout was tied to the now closed terminal. Correct?)

  3. bash -c "./foo &"

    Appears to behave exactly like 2).

  4. ./bar

    Appears to behave exactly like 2) and 3).

  5. Adding bash -c "~/foo" (no &) as a startup application

    Behaves similarly to 2), 3) and 4), with the differences:

    • Its controlling terminal is the desktop ttyx.
    • You can't (can you?) kill its controlling terminal.

    None of those differences seem odd to me, just the fact that it's continuously fed with new input.

My guess is that 2) - 5) all use a subshell of sorts whose stdin is redirected to something like /dev/null, though I'm very unsure and seek a more exact answer.

3
  • Try adding echo $? after read data to see if the read was successful.
    – Barmar
    Aug 15, 2018 at 18:24
  • EOF is not a character, it's a condition ("nothing more to read") of the input stream.
    – Kusalananda
    Dec 20, 2018 at 7:41
  • @Barmar Didn't think of that, thanks for the tip.
    – user_
    Dec 21, 2018 at 15:02

2 Answers 2

1

commands run with & in a shell without the job control enabled (eg. in a script or a (...) subshell) have their stdin redirected from /dev/null and SIGINT and SIGQUIT set to SIG_IGN. From the susv4 standard:

If job control is disabled (see set, -m), the standard input for an asynchronous list, before any explicit redirections are performed, shall be considered to be assigned to a file that has the same properties as /dev/null. This shall not happen if job control is enabled. In all cases, explicit redirection of standard input shall override this activity.

See also this and this.

It's not true that your ./foo script is "continuously fed" data -- it's getting an EOF when trying to read from /dev/null -- you should check the exit status of read.

6
  • It doesn't stop on EOF because there's no test on whether the read succeeded.
    – Kusalananda
    Dec 20, 2018 at 7:43
  • 1
    @Kusalananda That's was kind of an awkward retorical question, it should've been "why aren't you checking the exit status of read in your script".
    – user313992
    Dec 20, 2018 at 7:46
  • Ah. Yes. I did kinda misunderstand.
    – Kusalananda
    Dec 20, 2018 at 7:48
  • That's very interesting, thank you! Regarding not checking for EOF: For some reason I thought the read would attempt to read past EOF and then crash the script, instead of endlessly reporting EOF, not sure where I got that idea from...
    – user_
    Dec 21, 2018 at 14:17
  • However, there's something I'm missing. The susv4 standard says that the ignored action for those signals is inherited from the executing shell. Doesn't that imply that the executing shell also ignores those signals? Because that doesn't appear to be the case. Are they ignored and then uningnored? (Edit: At first this comment also asked about SIGHUP, but I believe you answered that in the second referenced answer.)
    – user_
    Dec 21, 2018 at 18:04
0

Your sub shells are non-interactive; only interactive shells are automatically killed.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .