Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 使用OCaml安全地执行外部程序_Unix_Ocaml - Fatal编程技术网

Unix 使用OCaml安全地执行外部程序

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.

如果外部程序调用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.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信号,通道将关闭。”