如何完全分离进程

如何完全分离进程

我想生成一个进程并在顶层运行它,以便当 shell 退出时,该进程继续运行。

我错误地认为 nohup 会执行此操作,但是当我退出 shell(shell 是一个 lxc 容器,我通过 ssh 进入该容器)并重新进入时,该进程消失了。

看起来(查看 pstree)即使使用 nohup 或 disown,该进程仍然位于调用 shell 下。

我尝试了几个选项,setsid 似乎有效 - 但我在这里的 nohup 做错了什么吗?

$ cat myproc
sleep 1234

$ myproc &
$ pstree -a | grep -B 3 "1234" | grep -v grep
  |-screen 
  |   |-bash -ls
  |   |   |-bash -ls
  |   |   |   `-sleep 1234


$ nohup myproc &
$ pstree 
  |-screen 
  |   |-bash -ls
  |   |   |-pstree -a
  |   |   `-sh ./myproc
  |   |       `-sleep 1234

$ myproc &
$ disown $!
$ pstree -a | grep -B 3 "1234" | grep -v grep
  |-screen 
  |   |-bash -ls
  |   |   |-bash -ls
  |   |   |   `-sleep 1234

$ setsid myproc &
  |-sh ./myproc
  |   `-sleep 1234

成功。但为什么 nohup 没有达到同样的效果呢?有没有更正确使用nohup的方法?

答案1

诊断有点困难,因为您没有提供 的来源myproc,但我怀疑您的问题与“控制 TTY“。我写了一个小的 shell 脚本,只调用sleep 100。我在下面运行它nohup

$ nohup ./sleeper > sleeper.out &

[1] 25305
-bash-3.2$ jobs
[1]+  Running                 nohup ./sleeper > sleeper.out &
-bash-3.2$ ps -l -p 25305
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S 429624 25305 18252  0 77   0 - 15961 wait   pts/0    00:00:00 sleeper

如果查看ps输出,您会看到名为“电传打字机”。至少有一些版本nohup(我上面使用的版本来自 GNU coreutils,版本 5.97,所以相对较旧)。当我退出启动的 bash shell 时sleeper,TTY 列更改为“?”,这意味着sleeper没有“没有一个。

如果myproc不故意将其自身与控制 TTY 分离,则在尝试写入 stdout 时仍然可以获得 SIGPIPE 信号之类的信息。在我看来,其他事情也是可能的,但我不记得或谷歌任何东西。

如果你能找到或编译“守护进程”,你可能想尝试一下。如果myproc编译通过,你可以修改源码来调用daemon(3)库函数。

答案2

您可以使用at为了这。

at实用程序应从标准输入读取命令并将它们组合在一起作为一个在职,稍后执行。

在职应在 shell 的单独调用中执行,在没有控制终端的单独进程组中运行,但环境变量、当前工作目录、文件创建掩码和其他实现定义的执行时属性在 at 时生效。实用程序被执行时应保留并使用在职被执行。

echo myproc | at now

...将工作,但在某些系统上您需要at首先配置该守护进程监视器。

答案3

要完全分离进程:

nohup ./command &

stdout 和 stderr 将写入名为 nohup.out 的文件,该文件位于执行 nohup 的同一目录中。

如果您希望在执行独立命令的同时能够在终端中查看输出,请使用 tail:

TEMP_LOG_FILE=tmp.log
> "$TEMP_LOG_FILE"
nohup ./command &> "$TEMP_LOG_FILE" & tail -f "$TEMP_LOG_FILE" &

相关内容