如何运行一个进程并将其与父 shell 完全分离

如何运行一个进程并将其与父 shell 完全分离

可能重复:
未登录时让 bash 脚本在远程终端上运行?
如何将一个进程从终端完全分离?

我正在 Linux 服务器上运行一个程序,需要几天时间才能完成。

我从我的工作站的 SSH 终端启动它,因为该程序仅仅是命令行。

我希望能够做到以下所有事情:

  • 启动该程序,
  • 将标准输出重定向到文件,
  • 退出我的 SSH 会话但不终止该进程。

我想过$ ./MyProg.csh -params -foo -bar </dev/null 1>~/out.log 2>~/err.log &

但是,当我关闭 SSH 会话时,该过程就会终止。我的工作站运行的是 Windows XP,我无法保证它能正常运行几天,而这是在 Linux 服务器上处理我的数据所必需的。

您可能已经注意到,我的程序需要从 CSH 启动。

是否有可能做到这一点 ?

谢谢。

答案1

您可以使用screennohup

如果你选择screen

screen在运行服务之前启动:

$ screen

然后,在里面运行你的服务screen

./MyProg.sh > myprog.log(或任何您想要的东西)。

然后Ctrl+a d

当你回来时,只需:

$ screen -r

了解更多信息:http://www.gnu.org/s/screen/


关于 nohup :只是:

nohup ./MyProg.sh > myprog.log &

答案2

制作一个像这样的外壳包装器:

#!/bin/sh
exec </dev/null
exec >> ~/out.log
exec 2>> ~/err.log
exec setsid ./MyProg.csh -params -foo -bar

如果您也需要 PID 文件,请将此 shell 脚本发送到 bg 并读取 $!(最后一个 bg 进程的 PID)。您可以在同一个脚本中使用带有 () 的子 shell 执行此操作,如下所示:

#!/bin/sh
( exec </dev/null
  exec >> ~/out.log
  exec 2>> ~/err.log
  exec setsid ./MyProg.csh -params -foo -bar
) &
kill -0 $! > /dev/null 2>&1 || exit 1
echo $! > program.pid
exit 0

答案3

连接断开是因为 shell 在退出时会向所有子进程发送 SIGHUP。如果您使用 bash 或 zsh,则可以使用disown,这样 shell 将不再发送 SIGHUP,进程将保留。

screensetsid以上方法均可行,但此答案的优点在于,在开始任何操作之前无需记住执行屏幕操作。 screen除此之外,它还有很多其他功能,因此您可能想要养成使用它的习惯。

相关内容