2

In a posix shell I would like to pass data to a background child process file descriptor and process output from the child in the parent.

No mkfifo please, just standard posix shell file descriptor duplication. No non-posix features like process substitions (<(cmd)). No intermediate files. No /dev/fd or /dev/std{in,out,err} or /proc/pid.

Something like the following (which isn't working, so somewhere my concepts, and thus likely some of the comment annotations, are muddled):

child()
{
  sed '1s|^|child: |;q'   # prepend 'child: ' to first input line and quit
}

exec 4>&1           # open file descriptor 4 duplicated as stdout

# give the shell some time to start the child, then send data to child via fd 4
{ sleep 2; echo foo >&4; } &

out=$(child 4<&0)   # connect fd 4 to stdin in child process

echo "out: $out"

I was hoping to see 'child: foo' in out. But instead I see foo on stdout and child() never terminates (so clearly the data is not going to the input file descriptor of the child).

Update: Adding a use case, per request.

In a loop, send data to a utility that reads stdin without having to re-spawn said utility each time through the loop. Having to re-fork/exec the utility every time through the loop is expensive. So... run utility as a background child process (exec just once) and send data from parent via the input file descriptor available to the child.

Update 2:

I guess I'm really trying to do what mkfifo does (create a in/out pair of fds where the output fd in the parent is connected to the input fd of the child, and the out fd of the child to the in fd of the parent), but without mkfifo being available (and if possible without temporary pipe files - i.e., just using anonymous file descriptors).

13
  • 1
    You can't do that without fifos or temporary files. There are workarounds in some shells, but they're all using extensions. (Notice that this has nothing to do with the child running in the fg/bg, but with the shell not having any way to create anonymous pipes other that via the cmd | cmd syntax). FWIW, exec 1>&4 will not work unless fd 4 is already opened, in which case it will make fd 1 (stdout) an alias of it (dup2(4, 1)).
    – mosvy
    Nov 16, 2019 at 18:30
  • Can you add to your question what (not how) you are trying to do. Nov 16, 2019 at 18:36
  • @ctrl-alt-delor: I added a use case, which may or may not help clarify. Specifically in the simplified example, I want to send data via a numbered file descriptor to a child process. So child should be waiting on a read of fd 4 and I want to pass data to fd 4 in the parent (and have the child read and act on that data).
    – Juan
    Nov 16, 2019 at 18:52
  • 1
    For the use case from your update: while :; do echo yup; done | your_utility. (yes, that does work; it may be that your_utility is using buffered i/o). As to your "mkfifo or tempfiles without mkfifo or tempfiles", you're free to think I'm talking out of my ass; but if you really have a problem, better explain what you're trying to achieve exactly, maybe there are better ways to do it than the one you have latched onto.
    – mosvy
    Nov 16, 2019 at 20:24

1 Answer 1

0

(not an answer, a long comment) Some similar questions:

1
  • Thanks. I've already searched quite a bit. I did not find any hits. The links you provided do not answer the question. Most of them point to mkfifo which is not available on some embedded systems I am targeting (and it can be weaker security-wise than file descriptor redirection since it creates a file on the filesystem that can be more easily accessed by unauthorized processes).
    – Juan
    Nov 16, 2019 at 18:58

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.