何时使用 Ruby 中启动子进程的每种方法

发布于 2024-12-01 10:45:11 字数 2761 浏览 0 评论 0原文

1. `` 反引号

1. a) %x{} 百分比 X < 在 parse.y 中定义的反引号的替代语法

2. system()

3. fork ()

4. open()

4.a。 IO.popen() IO.popen() IO.popen() 相同

4.b。 open("|-")

  • 分叉到管道

4.c. IO.popen("-") < 行为相同

  • open("|-") fork 到管道的
  • ,请参阅

5. Open3.popen3()

  • require 'open3'
  • stdlib Open3

6. PTY.spawn()

  • 需要'pty'
  • stdlib PTY

7. Shell.transact()

  • require 'shell'
  • stdlib Shell

什么时候应该放弃可靠的反勾号以使用一种更复杂的方法?

编辑1。 非常感谢 Avdi Grimm 描述每种方法示例用法的帖子:#1 (& 要点); #2(& 要点); #3

它们是回答如何的绝佳资源,但没有明确地回答何时使用为什么,因此恕我直言,它们不是这个问题的完整答案。

1. `` The Backtick

1. a) %x{} Percent X < alternate syntax for The Backtick

2. system()

3. fork()

4. open()

4.a. IO.popen() < behaves the same as open()

4.b. open("|-")

  • fork to a pipe

4.c. IO.popen("-") < behaves the same as open("|-")

5. Open3.popen3()

  • require 'open3'
  • stdlib Open3

6. PTY.spawn()

  • require 'pty'
  • stdlib PTY

7. Shell.transact()

  • require 'shell'
  • stdlib Shell

When should one forsake the trusty back-tick for one of the more complex methods?

Edit 1.
Big thanks to Avdi Grimm for his posts describing example usage of each method: #1 (& gist); #2 (& gist); #3.

They are fantastic resources to answer How, but are not explicitly composed to answer when each should be used or Why, and as such IMHO are not complete answers to this question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

东北女汉子 2024-12-08 10:45:11
  1. 当您想要轻松捕获变量中的程序输出时,请使用反引号。您可能只想将其用于短期运行的程序,因为这会阻塞。

  2. system 在两种不同的情况下很方便:

    a.您有一个长时间运行的程序,并且希望在运行时打印输出(例如 system("tar zxvf some_big_tarball.tar.gz"))

    b. system 可以像 exec 一样绕过 shell 扩展(比较 system "echo *"system "echo", "* “)

    系统会阻塞,直到子进程退出。

  3. fork 也有几个不同的用例:

    a.您想要在单独的进程中运行一些 ruby​​ 代码(例如 fork { .... }

    b.您希望运行子进程(或不同的程序)而不阻止脚本的进度 fork { exec "bash" }

    如果您想守护程序,

    fork 是您的朋友。

  4. IO.popen 在您需要时很有用。与程序的标准输出和标准输入交互。它不会捕获标准错误,因此如果您关心的话,您需要使用 2>&1 重定向它。

  5. popen3 为您提供一个单独的标准错误文件描述符(当您需要从标准输出中单独捕获该文件时)

  6. 当您希望生成的程序像从终端运行一样时,

    PTY.spawn 是必需的。查看使用 system 生成时 grep --color=auto pat filePTY.spawn

    PTY 的区别

  1. use backticks when you want to easily capture the output of a program in a variable. you probably only want to use this for short-running programs, because this will block.

  2. system is convenient in two different cases:

    a. You have a long running program and you want the output to print as it runs (e.g. system("tar zxvf some_big_tarball.tar.gz"))

    b. system can bypass the shell expansion like exec (compare the output of system "echo *" and system "echo", "*")

    system blocks until the subprocess has exited.

  3. fork has a couple different use cases as well:

    a. You want to run some ruby code in a separate process (e.g. fork { .... }

    b. You want to run a child process (or different program) without blocking progress of your script fork { exec "bash" }.

    fork is your friend if you want to daemonize your program.

  4. IO.popen is useful when you need to interact with the standard out and standard in of a program. Note that it doesn't capture standard err, so you need to redirect that with 2>&1 if you care about that.

  5. popen3 gives you a separate file descriptor for standard error (for when you need to capture that separately from standard out)

  6. PTY.spawn is necessary when you want the spawned program to behave like you are running from the terminal. See the difference of grep --color=auto pat file when spawned with system vs PTY.spawn

如梦初醒的夏天 2024-12-08 10:45:11

这是基于此答案的流程图。另请参阅使用脚本模拟终端

输入图像描述这里

Here's a flowchart based on this answer. See also, using script to emulate a terminal.

enter image description here

絕版丫頭 2024-12-08 10:45:11

除了上面的流程图https://stackoverflow.com/a/30463900/1211266,以防有人想要它markdown 中的可编辑流程图(由 美人鱼),这里是:

```mermaid
flowchart TD

A{{"Do I want to return to my ruby script, ever?"}} -- No --> B(["Use exec()"])
A -- Yes --> C{{"Is it OK to block until the process completes?"}}
C -- Yes --> D{{"Do I need the program's output to be returned?"}}
D -- Yes --> E(["Use backticks `` or %x{}"])
D -- No --> F(["Use system()"])
C -- No --> H{{"Do I need to interact with the output?"}}
H -- Yes --> J{{"Do I want STDERR?"}}
H -- No --> I(["Use fork()"])
J -- Yes --> L{{"Do I want STDERR in its own separate stream?"}}
J -- No --> K(["Use IO.popen()"])
L -- Yes --> M(["Use Open3.popen3()"])
L -- No --> N{{"Use PTY.spawn()"}}

O>"Outputs to STDOUT"] -.- F
P>"You can always emulate a terminal with the BSD utility called script"] -.- H
Q>"Separate child process; good for daemonizing"] -.- I
R>"You can still use 2>&1 to combine STDERR with STDOUT"] -.- K
S>"Emulates a terminal unconditionally"] -.- M

classDef decision fill:#f8fb99;
classDef action fill:#ffaead;
classDef note fill:#ddd,opacity:0.9,font-weight:200;

class A,C,D,H,J,L decision;
class B,E,F,I,K,M,N action;
class O,P,Q,R,S note;
```

In addition to the flowchart above https://stackoverflow.com/a/30463900/1211266, in case somebody wants it as an editable flowchart in markdown (powered by mermaid), here it is:

```mermaid
flowchart TD

A{{"Do I want to return to my ruby script, ever?"}} -- No --> B(["Use exec()"])
A -- Yes --> C{{"Is it OK to block until the process completes?"}}
C -- Yes --> D{{"Do I need the program's output to be returned?"}}
D -- Yes --> E(["Use backticks `` or %x{}"])
D -- No --> F(["Use system()"])
C -- No --> H{{"Do I need to interact with the output?"}}
H -- Yes --> J{{"Do I want STDERR?"}}
H -- No --> I(["Use fork()"])
J -- Yes --> L{{"Do I want STDERR in its own separate stream?"}}
J -- No --> K(["Use IO.popen()"])
L -- Yes --> M(["Use Open3.popen3()"])
L -- No --> N{{"Use PTY.spawn()"}}

O>"Outputs to STDOUT"] -.- F
P>"You can always emulate a terminal with the BSD utility called script"] -.- H
Q>"Separate child process; good for daemonizing"] -.- I
R>"You can still use 2>&1 to combine STDERR with STDOUT"] -.- K
S>"Emulates a terminal unconditionally"] -.- M

classDef decision fill:#f8fb99;
classDef action fill:#ffaead;
classDef note fill:#ddd,opacity:0.9,font-weight:200;

class A,C,D,H,J,L decision;
class B,E,F,I,K,M,N action;
class O,P,Q,R,S note;
```
生生不灭 2024-12-08 10:45:11

另外,还有 Process.spawn。来自文档:

此方法与 Kernel#system 类似,但它不等待
命令完成。

父进程应该使用Process.wait来收集终止信息
其子级的状态或使用 Process.detach 来注册不感兴趣
他们的地位;否则,操作系统可能会积累僵尸
流程。

Also, there is Process.spawn. From the docs:

This method is similar to Kernel#system but it doesn't wait for the
command to finish.

The parent process should use Process.wait to collect the termination
status of its child or use Process.detach to register disinterest in
their status; otherwise, the operating system may accumulate zombie
processes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文