Ocaml lwt 从其他进程读取标准输出
Ocaml lwt read stdout from other process
我正尝试在 Ocaml 中为基于终端的应用程序构建一个新的前端。主要思想是使用 Lwt 生成一个新进程:
let cmd = shell "./otherterminalapp" in
let p = open_process_full cmd;
然后将内容写入进程的标准输入,以在外部应用程序中执行命令。
Lwt_io.write_line p#stdin "some command" >>= (fun _ -> Lwt_io.flush p#stdin)
当我使用 Lwt_io.read_line_opt
从命令中读取结果时。我怎么读到没有剩下任何行?
我遇到的问题是我的程序只是挂在某个点。当我用 read_line_opt
阅读时,当我读到最后时,它似乎只是在等待进程重定向新输出。
我该如何解决这个问题?
我正在尝试做的一个具体例子:
(基于终端的应用程序是 ocamldebug)
程序源代码:
open Lwt
open Lwt_unix
open Lwt_process
let () =
let run () =
let cmd = shell "ocamldebug test.d.byte" in
let dbgr = open_process_full cmd in
(((((((Lwt_io.write_line dbgr#stdin "info modules") >>=
(fun _ -> Lwt_io.flush dbgr#stdin))
>>= (fun _ -> Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt.return ()) in
Lwt_main.run (run ())
如果您通常 运行 ocamldebug
和 test.d.byte
,您会得到
在您的终端中关注:
OCaml Debugger version 4.03.0
(ocd) info modules
Loading program... done.
Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
(ocd)
当我执行上面的程序时,我打印了以下内容:
OCaml Debugger version 4.03.0
(ocd) Loading program... Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
在这里它只是挂起...,我的程序没有退出。即使我这样做
Ctrl-c/Ctrl-c 在我的终端中,有一个活动的 ocaml运行 进程。但是,终端会变得有响应。
我在这里遗漏了一些明显的东西?
调用 Lwt.read_line_opt
returns 延迟值,一旦通道读取换行符终止的字符串,将在将来确定为 Some data
,或使用 None
如果通道已关闭。如果存在文件结束条件,通道将关闭。对于常规文件,文件结束条件发生在文件指针到达文件末尾时。对于用于与子进程通信的管道,当另一端关闭与管道关联的文件描述符时,会发生文件结束条件。
ocamldebug
程序不会关闭其输入或输出。它是一个交互式程序,可以无限期地与用户交互,或者直到用户通过点击 Ctrl-D
或使用 quit
命令关闭程序。
在您的场景中,您将 info modules
命令写入频道的输入。该进程以三行响应(其中每行是一段以换行符终止的数据)。然后子进程开始等待下一个输入。您没有看到 (ocd)
提示,因为它不是由换行符终止的。程序没有挂断。它还在等待子进程的输出,子进程也在等待你的输入(死锁)。
如果你真的需要区分不同命令的输出,那么你需要跟踪子进程输出中的提示。由于提示符未被换行符终止,因此您不能依赖 read_line*
系列函数,因为它们是行缓冲的。您需要阅读所有可用字符并手动在其中找到提示。
另一方面,如果你真的不需要区分不同命令的输出,那么你可以忽略提示(实际上,你甚至可以将其过滤掉,以获得更好的输出)。在那种情况下,您将有两个并发子例程——一个负责提供输入,另一个将读取所有输出并转储它,而不实际携带数据内容。
我正尝试在 Ocaml 中为基于终端的应用程序构建一个新的前端。主要思想是使用 Lwt 生成一个新进程:
let cmd = shell "./otherterminalapp" in
let p = open_process_full cmd;
然后将内容写入进程的标准输入,以在外部应用程序中执行命令。
Lwt_io.write_line p#stdin "some command" >>= (fun _ -> Lwt_io.flush p#stdin)
当我使用 Lwt_io.read_line_opt
从命令中读取结果时。我怎么读到没有剩下任何行?
我遇到的问题是我的程序只是挂在某个点。当我用 read_line_opt
阅读时,当我读到最后时,它似乎只是在等待进程重定向新输出。
我该如何解决这个问题?
我正在尝试做的一个具体例子: (基于终端的应用程序是 ocamldebug)
程序源代码:
open Lwt
open Lwt_unix
open Lwt_process
let () =
let run () =
let cmd = shell "ocamldebug test.d.byte" in
let dbgr = open_process_full cmd in
(((((((Lwt_io.write_line dbgr#stdin "info modules") >>=
(fun _ -> Lwt_io.flush dbgr#stdin))
>>= (fun _ -> Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt_io.read_line_opt dbgr#stdout))
>>=
(fun s ->
(match s with
| Some l -> print_endline l
| None -> print_endline "nothing here! ");
Lwt.return ()) in
Lwt_main.run (run ())
如果您通常 运行 ocamldebug
和 test.d.byte
,您会得到
在您的终端中关注:
OCaml Debugger version 4.03.0
(ocd) info modules
Loading program... done.
Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
(ocd)
当我执行上面的程序时,我打印了以下内容:
OCaml Debugger version 4.03.0
(ocd) Loading program... Used modules:
Std_exit Test Pervasives CamlinternalFormatBasics
在这里它只是挂起...,我的程序没有退出。即使我这样做 Ctrl-c/Ctrl-c 在我的终端中,有一个活动的 ocaml运行 进程。但是,终端会变得有响应。
我在这里遗漏了一些明显的东西?
调用 Lwt.read_line_opt
returns 延迟值,一旦通道读取换行符终止的字符串,将在将来确定为 Some data
,或使用 None
如果通道已关闭。如果存在文件结束条件,通道将关闭。对于常规文件,文件结束条件发生在文件指针到达文件末尾时。对于用于与子进程通信的管道,当另一端关闭与管道关联的文件描述符时,会发生文件结束条件。
ocamldebug
程序不会关闭其输入或输出。它是一个交互式程序,可以无限期地与用户交互,或者直到用户通过点击 Ctrl-D
或使用 quit
命令关闭程序。
在您的场景中,您将 info modules
命令写入频道的输入。该进程以三行响应(其中每行是一段以换行符终止的数据)。然后子进程开始等待下一个输入。您没有看到 (ocd)
提示,因为它不是由换行符终止的。程序没有挂断。它还在等待子进程的输出,子进程也在等待你的输入(死锁)。
如果你真的需要区分不同命令的输出,那么你需要跟踪子进程输出中的提示。由于提示符未被换行符终止,因此您不能依赖 read_line*
系列函数,因为它们是行缓冲的。您需要阅读所有可用字符并手动在其中找到提示。
另一方面,如果你真的不需要区分不同命令的输出,那么你可以忽略提示(实际上,你甚至可以将其过滤掉,以获得更好的输出)。在那种情况下,您将有两个并发子例程——一个负责提供输入,另一个将读取所有输出并转储它,而不实际携带数据内容。