I found this topic when encountering a similar problem, and experienced several challenges I did not expect to face. Still, I found the discussion extremely helpful!
I’ve spent several hours trying to figure out things that were not documented and I haven’t found anywhere else, so I would like to share my findings to save someone else some time (especially beginners).
-
Close channels only after reading them.
This is mentioned in the middle of the discussion but I wanted to highlight this separately. -
Unix.open_process_fulldoesn’t pass environment variables to the running process.
So if you expect the running command to have access to env variables like$HOME, you need to set them explicitly. -
Use
Unix.systemto run commands with all env variables passed and original output preserved.
If you don’t care about reading the output of the process, theUnix.systemfunction is the easiest way to run external processes from an OCaml program. -
Basedoesn’t have thecommandfunction in theSysmodule.
Two modules inbaseand OCaml stdlib are different but still look the same. I’ve spent an unreasonable amount of time trying to figure out why I can useSys.commandwhen in fact I hadopen Base. Some StackOverflow answers mention this function for running external processes. UseUnix.systeminstead. -
You can’t preserve the original interleaved output of
stdoutandstderrwhen reading the process output.
Or at least, I haven’t found the way. But usually the process output text to bothstdoutandstderrin arbitrary order, and you can’t preserve this order if you reading from the corresponding handles independently.
Based on the above, I’ve implemented a small interface for running external processes and reading their output in my recent tool: