0

In a shell script, I am trying to start a background command that has the same stdin as that of the shell script.

#!/bin/sh
# ...

the-program &

However, the-program above will not have access to the same standard input as that of the shell script. According to my shell's manual (dash(1)):

If the shell is not interactive, the standard input of an asynchronous command is set to /dev/null.

I have tried the-program & <&0 but it does not seem to have the intended effect; the standard input of the-program is still /dev/null.

I thought about creating a new file descriptor by duplicating the standard input of the shell script and somehow pass that new file descriptor to the background process. However, the background process must then somehow redirect that new file descriptor to its standard input (replacing /dev/null). I have no idea if this idea is even possible, and I do not know how to implement it in POSIX sh.

3
  • This sounds like an XY problem. What's the root problem you're trying to solve? Having a background process access stdin from a terminal does not make sense. It will fight with either the shell or whichever other command might be running in the foreground for that input.
    – muru
    Nov 7, 2023 at 15:59
  • Further to Muru's comment; it's hard to immagine what you are trying to achieve specifically because this would, at best, result in losing control of the forground shell until the background process completed. That would make it useless to background the process. Nov 7, 2023 at 16:09
  • I wonder if what you are trying to achieve is this: unix.stackexchange.com/a/537429/20140 (Specifically Alexander Mill's answer to his own question). This doesn't create a background process in the usual sense as there's no job control on it. It does allow the foreground shell to send stdin input to a process which is not in the foreground. If that's what your looking for then it may help understand your question better. Nov 7, 2023 at 16:26

1 Answer 1

0

Yes, that's an annoying requirement of the POSIX sh specification that commands started asynchronously by non-interative shell invocations (when the monitor option IOW job control is not enabled) have their stdin redirected to /dev/null.

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.

The usual work around is to do:

{ cmd <&3 3<&- & } 3<&0

Which sounds like what you were thinking of.

Example:

$ sh -c 'readlink /proc/self/fd/0 & wait' < /
/dev/null
$ sh -c '{ readlink /proc/self/fd/0 <&3 3<&- & } 3<&0; wait' < /
/

Other option is to use zsh which ignores that requirement even in sh emulation:

$ zsh -c 'readlink /proc/self/fd/0 & wait' < /
/
$ zsh --emulate sh -c 'readlink /proc/self/fd/0 & wait' < /
/

You must log in to answer this question.

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