Miko Asked: 2010-02-24 12:17:46 +0800 CST2010-02-24 12:17:46 +0800 CST 2010-02-24 12:17:46 +0800 CST SSH 会话丢失 - 命令是否继续执行?[复制] 772 如果在 SSH 连接断开之前我正在运行命令,该命令会继续执行吗? ssh 6 个回答 Voted Best Answer Warner 2010-02-24T12:26:48+08:002010-02-24T12:26:48+08:00 在大多数情况下,没有。进程将在终端丢失时发送 SIGHUP。您可以在命令前加上“nohup”来忽略信号。看: http://en.wikipedia.org/wiki/Nohup geekifier 2010-09-22T14:26:33+08:002010-09-22T14:26:33+08:00 我将在线程中添加另一个有用的建议,这是我几分钟前刚刚学到的: 如果您已经启动了一个需要很长时间的进程(在我的例子中是 tar restore),并且忘记在它前面包含 nohup,您仍然可以防止它在注销时终止。 以下是步骤: 按Ctrl + Z - 这将暂停作业 输入disown -h %x,其中x是暂停作业后获得的作业编号 执行bg将作业置于后台 退出外壳并继续你的生活:)。 Dave Cheney 2010-02-24T12:29:39+08:002010-02-24T12:29:39+08:00 正如 Warner 上面所说,ssh 守护进程的子进程(即登录 shell 和它的子进程)将得到SIGHUP,但他们不会立即得到它们。会有延迟,有时在服务器端的 ssh 守护进程放弃连接之前几分钟。在此期间,该过程将继续运行。 正如 Warner 所说,进程可以选择忽略SIGHUP,在这种情况下,它将继续运行,直到它必须请求输入,然后 findSTDIN已经关闭。 mfinni 2010-02-24T12:28:13+08:002010-02-24T12:28:13+08:00 不是一般的,虽然不知道你正在运行什么外壳甚至什么操作系统,但很难说。例如,如果您在屏幕下运行它,我认为行为是分离并继续运行。也许其他一些 shell 将其作为可配置选项。 Zahid 2017-05-04T05:26:35+08:002017-05-04T05:26:35+08:00 我在下面的链接中找到了最佳答案 与 SSH 会话断开连接会杀死您的程序吗? 2016年编辑: 此问答早于 systemd v230 崩溃。从 systemd v230 开始,新的默认设置是杀死终止登录会话的所有子节点,无论采取了哪些历史上有效的预防措施来防止这种情况发生。可以通过在 /etc/systemd/logind.conf 中设置 KillUserProcesses=no 来更改行为,或者使用 systemd 特定的机制在用户空间中启动守护程序来规避。这些机制超出了这个问题的范围。 下面的文字描述了传统上事情在 UNIX 设计空间中的工作时间比 Linux 存在的时间更长。 他们会被杀死,但不一定会立即被杀死。这取决于 SSH 守护程序需要多长时间才能确定您的连接已失效。下面是一个较长的解释,将帮助您了解它的实际工作原理。 当您登录时,SSH 守护程序会为您分配一个伪终端并将其附加到您的用户配置的登录 shell。这称为控制终端。你在那个时候正常启动的每个程序,无论有多少层壳深,最终都会“追溯到它的祖先”回到那个壳。您可以使用 pstree 命令观察这一点。 当与您的连接关联的 SSH 守护进程确定您的连接已失效时,它会向登录 shell 发送挂断信号 (SIGHUP)。这会通知外壳您已经消失并且它应该开始自行清理;此时发生的事情是特定于 shell 的(在其文档页面中搜索“HUP”),但在大多数情况下,它会在终止之前开始发送 SIGHUP 到与其关联的正在运行的作业。反过来,这些进程中的每一个都会在收到该信号时执行它们配置为执行的任何操作。通常这意味着终止。如果这些工作有自己的工作,信号通常也会传递。 在控制终端挂断后幸存下来的进程要么与终端(您在其中启动的守护进程)解除关联,要么使用前缀 nohup 命令调用的进程。(即“不要挂断这个”) 终端多路复用器是在断开连接之间保持 shell 环境完整的常用方法。它们允许您以一种以后可以重新连接到它们的方式与您的 shell 进程分离,无论这种断开是偶然的还是故意的。tmux 和 screen 是比较流行的;使用它们的语法超出了您的问题范围,但值得研究。 有人要求我详细说明“SSH 守护程序需要多长时间才能确定您的连接已失效”。这是特定于 SSH 守护程序的每个实现的行为,但您可以指望它们在任何一方重置 TCP 连接时终止。如果任何一方尝试写入套接字并且 TCP 数据包未得到确认,这将很快发生,或者如果双方都没有尝试写入 PTY,则会缓慢发生。 在这种特殊情况下,最有可能触发写入的因素是: 一个进程(通常在前台)试图在服务器端(服务器->客户端)写入 PTY。用户尝试在客户端(客户端->服务器)写入 PTY。 任何形式的保活。默认情况下,这些通常不会被客户端或服务器启用,并且通常有两种风格:应用程序级别和基于 TCP 的(即 SO_KEEPALIVE)。Keepalives 相当于服务器或客户端不经常向另一端发送数据包,即使没有任何其他理由写入套接字。虽然这通常是为了避开那些过快连接超时的防火墙,但它具有额外的副作用,即当对方没有更快地响应时,它会导致发件人注意到。 TCP 会话的通常规则适用于此:如果客户端和服务器之间的连接中断,但在问题期间双方都没有尝试发送数据包,则连接将继续存在,前提是双方随后都做出响应并接收到预期的 TCP序号。 如果一方已经确定套接字已失效,则效果通常是立竿见影的:sshd 进程将发送 HUP 并自行终止(如前所述),或者客户端将通知用户检测到的问题。值得注意的是,仅仅因为一方认为另一方已死并不意味着另一方已收到通知,并且通常会保持打开状态,直到它尝试写入连接或接收到来自另一方的 TCP 重置. (如果当时连接可用) Christopher Karel 2010-02-24T12:28:51+08:002010-02-24T12:28:51+08:00 华纳的回答是正确的。或者,您也可以在后台执行该命令,方法是在命令末尾附加一个与号 (&)。
在大多数情况下,没有。进程将在终端丢失时发送 SIGHUP。您可以在命令前加上“nohup”来忽略信号。看:
http://en.wikipedia.org/wiki/Nohup
我将在线程中添加另一个有用的建议,这是我几分钟前刚刚学到的:
如果您已经启动了一个需要很长时间的进程(在我的例子中是 tar restore),并且忘记在它前面包含 nohup,您仍然可以防止它在注销时终止。
以下是步骤:
正如 Warner 上面所说,ssh 守护进程的子进程(即登录 shell 和它的子进程)将得到
SIGHUP
,但他们不会立即得到它们。会有延迟,有时在服务器端的 ssh 守护进程放弃连接之前几分钟。在此期间,该过程将继续运行。正如 Warner 所说,进程可以选择忽略
SIGHUP
,在这种情况下,它将继续运行,直到它必须请求输入,然后 findSTDIN
已经关闭。不是一般的,虽然不知道你正在运行什么外壳甚至什么操作系统,但很难说。例如,如果您在屏幕下运行它,我认为行为是分离并继续运行。也许其他一些 shell 将其作为可配置选项。
我在下面的链接中找到了最佳答案
与 SSH 会话断开连接会杀死您的程序吗?
2016年编辑:
此问答早于 systemd v230 崩溃。从 systemd v230 开始,新的默认设置是杀死终止登录会话的所有子节点,无论采取了哪些历史上有效的预防措施来防止这种情况发生。可以通过在 /etc/systemd/logind.conf 中设置 KillUserProcesses=no 来更改行为,或者使用 systemd 特定的机制在用户空间中启动守护程序来规避。这些机制超出了这个问题的范围。
下面的文字描述了传统上事情在 UNIX 设计空间中的工作时间比 Linux 存在的时间更长。
他们会被杀死,但不一定会立即被杀死。这取决于 SSH 守护程序需要多长时间才能确定您的连接已失效。下面是一个较长的解释,将帮助您了解它的实际工作原理。
当您登录时,SSH 守护程序会为您分配一个伪终端并将其附加到您的用户配置的登录 shell。这称为控制终端。你在那个时候正常启动的每个程序,无论有多少层壳深,最终都会“追溯到它的祖先”回到那个壳。您可以使用 pstree 命令观察这一点。
当与您的连接关联的 SSH 守护进程确定您的连接已失效时,它会向登录 shell 发送挂断信号 (SIGHUP)。这会通知外壳您已经消失并且它应该开始自行清理;此时发生的事情是特定于 shell 的(在其文档页面中搜索“HUP”),但在大多数情况下,它会在终止之前开始发送 SIGHUP 到与其关联的正在运行的作业。反过来,这些进程中的每一个都会在收到该信号时执行它们配置为执行的任何操作。通常这意味着终止。如果这些工作有自己的工作,信号通常也会传递。
在控制终端挂断后幸存下来的进程要么与终端(您在其中启动的守护进程)解除关联,要么使用前缀 nohup 命令调用的进程。(即“不要挂断这个”)
终端多路复用器是在断开连接之间保持 shell 环境完整的常用方法。它们允许您以一种以后可以重新连接到它们的方式与您的 shell 进程分离,无论这种断开是偶然的还是故意的。tmux 和 screen 是比较流行的;使用它们的语法超出了您的问题范围,但值得研究。
有人要求我详细说明“SSH 守护程序需要多长时间才能确定您的连接已失效”。这是特定于 SSH 守护程序的每个实现的行为,但您可以指望它们在任何一方重置 TCP 连接时终止。如果任何一方尝试写入套接字并且 TCP 数据包未得到确认,这将很快发生,或者如果双方都没有尝试写入 PTY,则会缓慢发生。
在这种特殊情况下,最有可能触发写入的因素是:
一个进程(通常在前台)试图在服务器端(服务器->客户端)写入 PTY。用户尝试在客户端(客户端->服务器)写入 PTY。
任何形式的保活。默认情况下,这些通常不会被客户端或服务器启用,并且通常有两种风格:应用程序级别和基于 TCP 的(即 SO_KEEPALIVE)。Keepalives 相当于服务器或客户端不经常向另一端发送数据包,即使没有任何其他理由写入套接字。虽然这通常是为了避开那些过快连接超时的防火墙,但它具有额外的副作用,即当对方没有更快地响应时,它会导致发件人注意到。
TCP 会话的通常规则适用于此:如果客户端和服务器之间的连接中断,但在问题期间双方都没有尝试发送数据包,则连接将继续存在,前提是双方随后都做出响应并接收到预期的 TCP序号。
如果一方已经确定套接字已失效,则效果通常是立竿见影的:sshd 进程将发送 HUP 并自行终止(如前所述),或者客户端将通知用户检测到的问题。值得注意的是,仅仅因为一方认为另一方已死并不意味着另一方已收到通知,并且通常会保持打开状态,直到它尝试写入连接或接收到来自另一方的 TCP 重置. (如果当时连接可用)
华纳的回答是正确的。或者,您也可以在后台执行该命令,方法是在命令末尾附加一个与号 (&)。