如何解雇并忘记子进程?

时间:2009-04-30 10:12:23

标签: ruby unix process fork

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

我设法通过从编程Ruby书中搜索一些代码来完成我所需要的工作,但我想找到最佳/正确的方法,并了解正在发生的事情。这是我最初得到的:

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


那么,这是方式,还是我应该怎么办?

检查下面的答案后,我最终得到了这段代码,这似乎更有意义:

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


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

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

5 个答案:

答案 0 :(得分:31)

Alnitak是对的。这是一种更明确的编写方式,没有$$

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

分离的目的只是说,“我不关心孩子什么时候终止”以避免zombie processes

答案 1 :(得分:20)

fork功能将您的流程分为两部分。

然后

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

因此:

exec("something") if fork.nil?

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

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

Process.detach()的调用看起来可能不正确。我原以为它会让孩子的PID在其中,但是如果我正确读取你的代码,它实际上是在分离父进程。

答案 2 :(得分:2)

脱离$$是不对的。从p。 Pickaxe(第二版)中的348个:

  

$$ Fixnum正在执行的程序的进程号。 [r / o]

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

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

答案 3 :(得分:2)

如果您确定要分离子进程,其他答案都很好。但是,如果您不介意,或者更愿意保留子进程(例如,您正在为Web应用程序启动子服务器/服务),那么您可以利用以下简写

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

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

答案 4 :(得分:0)

我发现上面的答案打破了我的终端并弄乱了输出。这是我找到的解决方案。

   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