我想生成一个进程并在顶层运行它,以便当 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" &