Unix 使用OCaml安全地执行外部程序
如果外部程序调用stuck或突然请求输入(由于某些错误),是否可以以某种方式避免挂起OCaml程序 例如,我使用7zip解包不同格式的存档数据,代码如下:Unix 使用OCaml安全地执行外部程序,unix,ocaml,Unix,Ocaml,如果外部程序调用stuck或突然请求输入(由于某些错误),是否可以以某种方式避免挂起OCaml程序 例如,我使用7zip解包不同格式的存档数据,代码如下: let exec_un7zip ~dpath ~fpath = let cmdline = "7z x -aoa -o \"" ^ dpath ^ "\" \"" ^ fpath ^ "\"" in Printf.printf "exec (%s)\n" cmdline; let stdout = Core.Unix.
let exec_un7zip ~dpath ~fpath =
let cmdline = "7z x -aoa -o \"" ^ dpath ^ "\" \"" ^ fpath ^ "\"" in
Printf.printf "exec (%s)\n" cmdline;
let stdout = Core.Unix.open_process_in cmdline in
Core.In_channel.input_all stdout |> ignore;
stdout
如果7zip遇到错误或要求额外输入,尽管提供了标志,是否可能有超时或其他方式来完成执行?OCaml的标准(带有Sys
模块)和Unix
库提供了两个应能完成此任务的函数。Core
中可能有同等/更高级别的函数,因为您似乎在使用它,但我没有检查:
将在Unix.alarm n
秒后发出信号n
sigalrm
将在每次引发Sys.sigalrm.Sys.sigalrm(Sys.signal\u handle(fun->do\u something())
时运行Sys.sigalrm
。例如,在适当的进程上调用do\u something()
。此外,Unix.kill
返回给定信号的旧处理程序,以便以后可以恢复它Sys.signal
let cmd_timeout cmd args timeout =
let pid = Unix.create_process cmd args Unix.stdin Unix.stdout Unix.stderr in
let kill _ = Unix.kill pid Sys.sigterm in
let old = Sys.signal Sys.sigalrm (Sys.Signal_handle kill) in
let _ = Unix.alarm timeout in
try
let _, res = Unix.waitpid [] pid in
(match res with
| Unix.WEXITED d ->
Printf.printf "Exited with status %d\n%!" d
| Unix.WSIGNALED d ->
Printf.printf "Signalled with %d\n%!" d
| Unix.WSTOPPED d ->
Printf.printf "Stopped with %d\n%!" d);
Sys.set_signal Sys.sigalrm old
with Unix.Unix_error(Unix.EINTR, _, _) ->
Printf.printf "Timeout!\n%!"; Sys.set_signal Sys.sigalrm old
let () = cmd_timeout "sleep" [| "sleep"; "10" |] 3 (* will timeout *)
let () = cmd_timeout "sleep" [| "sleep"; "3" |] 10 (* will exit normally *)
我认为如果您分配一个伪tty并将其用于stdin,那么您可以捕获从stdin读取的命令。否则,您最好在后台启动命令,并在时间过长时将其杀死(不输出任何内容)。和库提供了管理外部进程的模块,而不会阻止生成进程。感谢您提供的信息。Lwt文档中写道:“以下所有函数都采用可选参数超时。如果指定,则在过期后,进程将发送一个Unix.sigkill信号,通道将关闭。”