nohup
我试图了解在 ssh 中使用后台命令的需要。我的 shell 在 CentOS 上是 csh。
即使 ssh 退出后,下面的后台命令也会继续运行。我预计只有在
nohup
命令前面加上前缀才会发生这种情况。什么场景下
nohup
会需要?ssh host 'sleep 80 >& /dev/null &'
我也尝试了交互式shell,ssh退出后后台作业的PID仍然存在于主机上。
ssh host sleep 80 >& /dev/null & exit
kill -HUP PID
我还尝试使用而不是终止交互式会话exit
,并且在ssh退出后后台作业的PID仍然存在于主机上。
我做错了什么吗?
答案1
不,一个背景默认情况下,当会话领导者(shell)退出或其控制终端被拆除时,进程组(作业)不会被终止。
只有一些特殊情况才会发生这种情况:
(1)后台作业是停止了SIGHUP
,在这种情况下,它将由/发送一SIGCONT
对信号核心。如果SIGHUP
进程没有捕获或忽略该信号,则该进程将终止。
已停止作业的定义是:任何包含已停止进程的作业。一个过程睡眠nanosleep(2)
在诸如或 之类的阻塞系统调用上,read(2)
不被视为已停止。
(2)进程尝试读取或写入不再存在的终端,并由于尝试执行此操作时出现错误而(自行)退出。
(3)这份工作实际上是一个前景工作。这核心SIGHUP
当会话领导者/控制进程(即 shell)终止时,向前台进程组发送信号。SIGHUP
当控制终端被拆除时,控制进程本身会收到信号,这通常会导致其终止。
即使以开头的命令&
实际上也是前景当它们从没有作业控制的 shell 启动时(在大多数 shell 中——但不是在 csh 中——是运行时的默认设置)脚本和子壳)。
(4)bash
您正在使用像or 这样的 shell zsh
,SIGHUP
当它本身收到信号时SIGHUP
(根据上面的第 3 点,shell 是控制进程),或者只是当它退出时(后者只是 中的默认值zsh
,但不是默认值并受shopt huponexit
bash 中的选项约束)。
这外壳程序(真实的csh
或tcsh
)没有这种行为从bash
或zsh
。在tcsh
(但不是在真实的csh
)中,您可以使用内置命令启动命令hup
,以便在 shell 退出时对其进行 hup 操作:
tcsh% hup sleep 3600 &
tcsh% exit
$ pgrep sleep
[nothing]
(5)您的 init 系统会不遗余力地清理任何终止的用户会话。在其默认配置下,系统会向所有进程发出信号范围延迟后跟随一个,所以无论如何SIGTERM
都不会帮助你。另外,systemd 的想法是SIGKILL
nohup
范围与 Unix 进程会话不匹配,因此运行命令setsid(1)
也不会让它逃脱。
您可以通过调整 、 和 选项的默认值来更改KillUserProcesses=yes
systemdKillMode=control-group
的KillSignal=SIGTERM
行为SendSIGKILL=yes
。