How can I do that?
Use direct file output in your program, or use additional fds.
As-is, your main program is getting the default stdout (conventionally fd 1) and the child processes just inherit that, so all children output directly to fd1 without any intermediate processing, or the ability to split the stream, they're literally writing to the same OS-level object.
The easiest way to fix this is to open 3 files in the main process, convert the files to Stdio
structures, then set that as the children's stdout
. This way the children will write to different files, and you can merge the files later, or not.
The alternative is somewhat more involved and unconventional: stdin, stdout, and stderr are just fds 0, 1, and 2. But nothing prevents having more of them, they just don't exist by default:
❯ python -c 'open(3, "a").write("ok")'
Traceback (most recent call last):
File "<string>", line 1, in <module>
OSError: [Errno 9] Bad file descriptor
❯ python -c 'open(3, "a").write("ok")' 3>&1
ok% ❯ python -c 'open(3, "a").write("ok")' 3>/dev/null
Doing the same in rust is a bit more complex, but you can use something like libc to try to open the relevant fds, if they exist convert them to owned fds then to Stdio
objects which you can pass to Command
.
If they don't exist, you can fallback to inheriting stdout, or to a File
-based Stdio
as above.
The outputs of the child processes don't have any prefix so it's impossible to figure out which output statement corresponds to which child process. Currently this is the output:
I don't think that's possible without an intermediate process which decorates output.
In that case what you'd do is spawn each child with an .stdout(Stdio::piped())
. From this you can get a ChildStdout
for each child, which you then convert to an Stdio
, which you can then pass as stdin
to a second process which reads lines from its input and adds a prefix of some sort (a different one for each child). You could just use sed
or awk
or ed
for that.
The second process would then inherit the stdout from the main / bootstrapping program, and every line from every child would get written out to the original stdout, just with a prefix.