如何触发和忘记一个subprocess?

我有一个漫长的过程,我需要它启动另一个过程(这也将运行很长一段时间)。 我只需要启动它,然后完全忘记它。

我设法通过从Ruby编程书中获取一些代码来做我所需要的,但是我想find最好的/正确的方法,并且理解正在发生的事情。 这是我最初得到的:

exec("whatever --take-very-long") if fork.nil? Process.detach($$) 

那么,是这样的,还是我该怎么做呢?

检查下面的答案后,我结束了这个代码,这似乎更有意义:

 (pid = fork) ? Process.detach(pid) : exec("foo") 

我会很感激fork如何工作的一些解释。 [已经得到]

分离$$正确吗? 我不知道为什么这样做,我真的很想更好地掌握情况。

fork函数将你的过程分成两部分。

两个进程都会收到该函数的结果。 孩子收到一个零/ nil的值(因此知道它是孩子),父母接收孩子的PID。

因此:

 exec("something") if fork.nil? 

将使子进程启动“某事”,父进程将继续进行。

请注意, exec()用“something” 替换当前进程,所以子进程永远不会执行任何后续的Ruby代码。

Process.detach()的调用看起来可能不正确。 我会期望它有它的孩子的PID,但是如果我读了你的代码,它实际上是分离父进程。

Alnitak是对的。 这里有一个更明确的写法,没有$$

 pid = Process.fork if pid.nil? then # In child exec "whatever --take-very-long" else # In parent Process.detach(pid) end 

分离的目的就是说“我不在乎孩子什么时候终止”,以避免僵尸进程 。

分离$$是不对的。 来自p。 镐348(第二版):

$$ Fixnum正在执行的程序的进程号。 [R / O]

本节“Ruby语言”一章中的“变量和常量”对解码各种ruby短$常量非常方便 – 但是在线版(第一个

所以你实际上在做的是把这个程序从它自己而不是从它的孩子中分离出来。 像其他人所说的那样,从孩子分离的正确方法是使用从fork()返回的孩子的pid。

如果您确定要分离子进程,其他答案是很好的。 但是,如果您不介意,或者希望保留附加的子进程(例如,您正在为Web应用程序启动子服务器/服务),则可以利用以下速记

 fork do exec('whatever --option-flag') end 

提供一个块告诉fork在子进程中执行该块(只有该块),同时继续在父进程中。

我发现上面的答案打破了我的终端,搞砸了输出。 这是我找到的解决方案。

  system("nohup ./test.sh &") 

以防万一任何人有相同的问题,我的目标是登录到一个SSH服务器,然后保持该进程无限期地运行。 所以test.sh是这样的

 #!/usr/bin/expect -f spawn ssh host -l admin -i cloudkey expect "pass" send "superpass\r" sleep 1000000