It seems that the pipe only becomes readable AFTER the process
terminates.
This is a pretty common phenomenon when dealing with pipes. If the child process does client-side buffering, data won’t show up on the parent side of the pipe until the client flushes its buffer.
As the parent, you don’t have direct control over the child’s buffering policy. Some programs have a command-line option to change their behaviour in this regard, although that’s pretty rare. Most programs use the default buffering policy described in the setvbuf
man page. If that’s the case then you can implicitly switch the policy by using pseudo-terminal rather than a pipe. See the pty
man page for more. It’s not much fun.
As a first step I recommend that you test the program from Terminal using cat
. Imagine a tool that prints data to stdout
periodically:
% cat main.swift
import Foundation
func main() {
while true {
print(Date.now)
sleep(1)
}
}
main()
% swiftc main.swift
If you run it directly from your shell, stdout
is connected to your terminal and you see lines of output each second:
% ./main
2023-03-27 07:55:38 +0000
2023-03-27 07:55:39 +0000
2023-03-27 07:55:40 +0000
^C
Now pipe the output to cat
:
% ./main | cat
^C
Here stdout
is connect to a pipe and the tool now buffers. If you leave it long enough, you’ll eventually see one giant blob of output.
So, run your tool in this way and see if its log messages show up promptly.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple