我浏览了这个问题的最佳答案:nohup、disown 和 & 之间的区别,我具体阅读了以下内容:
由于
disown
作业仍然连接到终端,因此如果终端被破坏(如果它是一个pty
,则可能发生这种情况,如由xterm
或创建的那些,并且通过关闭或终止连接SSH
来终止控制程序 ),程序将一旦它尝试从标准输入读取或写入标准输出,就会失败。xterm
SSH
disown
如果终端关闭, 它似乎无法阻止作业被杀死。nohup
可以,但只能在作业开始时使用。
假设我正确理解了这一点,我该怎么做才能确保我开始的工作没有 nohup
当我关闭终端、终止SSH
连接时不会被杀死吗?
setopt NO_HUP
从命令行发出可以吗?如果是这样,这不会影响我从同一终端启动的所有正在运行的作业吗?
答案1
对于标准 Shell (bash) (POSIX.1)
以 开始&
,让它从默认值以外的其他内容读取stdin
(== /dev/tty
== /dev/stdin
== /dev/fd/0
) + 使其写入默认值以外的内容stdout
(== /dev/tty
== /dev/stdin
== /dev/fd/1
) (与 相同stderr
)并确保该作业是' t 或没有被暂停(=停止了)。如果它必须停止或必须从终端读取并且要在作业终端挂起后继续,请确保作业中的进程有一个处理程序(陷阱)叹息信号。如果它必须写入终端并且要在终端挂起后继续存在,请确保写入终端的进程有一个处理程序信号管道。
解释:
后台进程被发送信号输入当他们尝试从终端读取数据的那一刻。默认配置为信号输入是停止(=暂停)进程。终端挂起将导致后台作业的第一代进程重新父级为 init,从而导致作业进程的第一代进程组成为孤立进程组。 (孤立进程组是指没有任何成员在不同进程组中但在同一会话中拥有父进程的进程组。)系统将发送所有已停止(挂起)的孤立进程组叹息其次是信号控制(以确保他们得到叹息)在终端挂起时,因为根据定义,该进程组中的任何进程都不能被同一会话的父进程唤醒。因此,这些进程必须由系统唤醒,但同时以某种方式向该进程发出信号,表明它是由于终端挂起而不是由于正常操作而被唤醒的。叹息是执行此操作的机制以及默认配置叹息就是中止。
挂起终端也会导致对该终端的后续写入引发信号管道,如果不处理的话也是致命的。
长话短说
如果您的孤立进程组没有暂停(通过信号输入或 ^Z 或其他,他们不必害怕叹息信号,如果它们输出到文件而不是终端,stdout
并且stderr
从文件而不是终端读取,那么它们不必害怕信号管道。如果您在终端多路复用器而不是原始终端上运行,则不必担心叹息或者信号管道。
对于zsh
我玩了一下zsh
,结果发现 while 的bash
行为确实像我上面描述的那样(上述行为应该符合 POSIX.1),zsh
发送叹息到跑步甚至是后台工作。
setopt NO_HUP
使其(或系统;此处不确定)仅SIGHUP
在上述情况下发送。
为了测试这一点,您可以尝试运行以下命令:
( rm -f hup; trap 'echo HUP > hup' HUP; sleep 100)
以各种方式(背景、前景、停止)并与其断开连接。然后您可以检查该hup
文件是否已创建,这意味着该作业确实获得了叹息。
答案2
您可能会发现尝试或很有用(尽管它不使用disown
,nohup
或&
)。这两种工具都允许您运行多个终端并与它们分离,而无需停止每个终端中发生的事情。我觉得比较方便。screen
tmux
tmux
使用tmux
您可以命名会话,
tmux new-session -s ${SESSION_NAME}
启动一个而不附加它,
tmux new-session -d -s ${SESSION_NAME} '/home/user/script.sh'
列出会话,
tmux list-sessions
甚至向他们发送命令:
tmux send-keys -t ${SESSION_NAME} "echo Hello world"
tmux send-keys -t ${SESSION_NAME} Enter
当然,您可以附加(“打开”)正在进行的会话以查看其中发生的情况:
tmux attach-session -t ${SESSION_NAME}
然后离开它而不关闭它,Ctrl + B
然后按D
。