题
我有一个漫长的运行过程,我需要它来启动另一个进程(也将运行一段时间)。我只需要启动它,然后完全忘掉它。
我设法通过从编程Ruby书中搜索一些代码来做我需要的东西,但我想找到最佳/正确的方法,并了解正在发生的事情。这是我最初得到的:
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?
将使子进程启动“some”,并且父进程将继续进行。
请注意, 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。 Pickaxe(第二版)中的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