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).
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)
). – Nov 16 '19 at 18:30coproc
command in various shells? – G-Man Says 'Reinstate Monica' Nov 16 '19 at 18:57out
to have the value 'child: foo' after the parent passes 'foo' to the child via a file descriptor? – Juan Nov 16 '19 at 19:05cmd | cmd
, the alternative to this is named pipes, and that's all – Nov 16 '19 at 19:18cmd|cmd
is the classic non-named piped way. But my input to the child is generated later in the script (scattered around in the real example not shown). Maybe it can't be done, as you say. – Juan Nov 16 '19 at 19:27cmd|cmd
is the classic non-named piped way exactly, and it's not possible in this case; you can not connect the current execution environment's stdout to another process' stdin from within the current execution environment itself, this must be done from the outside; and that's not what you want to do. This is probably why they created named pipes – Nov 16 '19 at 19:34while :; do echo yup; done | your_utility
. (yes, that does work; it may be thatyour_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. – Nov 16 '19 at 20:24