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_full
doesn’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.system
to run commands with all env variables passed and original output preserved.
If you don’t care about reading the output of the process, theUnix.system
function is the easiest way to run external processes from an OCaml program. -
Base
doesn’t have thecommand
function in theSys
module.
Two modules inbase
and 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.command
when in fact I hadopen Base
. Some StackOverflow answers mention this function for running external processes. UseUnix.system
instead. -
You can’t preserve the original interleaved output of
stdout
andstderr
when reading the process output.
Or at least, I haven’t found the way. But usually the process output text to bothstdout
andstderr
in 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: