结束 ssh 会话后如何保持进程运行?

Oli*_*nde 825 ssh

假设我从 ssh 会话启动了一堆进程。是否可以终止 ssh 会话,同时保持这些进程在远程计算机上运行?

ton*_*gpu 953

您应该寻找像tmux.

tmux优于screen很多原因,这里只是一些例子:

  • Windows 可以在会话之间移动,甚至可以链接到多个会话
  • 窗口可以水平和垂直拆分为窗格
  • 支持 UTF-8 和 256 色终端
  • 会话可以从外壳控制,无需进入会话

基本功能

要获得与推荐答案中解释的相同的功能screen,您需要执行以下操作:

  • ssh 进入远程机器
  • 首先在 shell 中tmux输入tmux
  • 在已启动的tmux会话中启动您想要的进程
  • tmux通过输入Ctrl+b然后离开/分离会话d

您现在可以安全地从远程机器注销,您的进程将继续在tmux. 当您再次回来并想要检查您的流程状态时,您可以使用tmux attach它附加到您的tmux会话中。

如果您希望多个会话并行运行,您应该使用Ctrl+b和命名每个会话$。您可以使用 获取当前正在运行的会话的列表tmux list-sessions,现在使用命令附加到正在运行的会话tmux attach-session -t <session-name>

tmux可以做比在单个会话中处理单个窗口更高级的事情。有关更多信息,请查看man tmuxtmux GitHub 页面。特别是,这里有一个关于screen和之间主要区别的常见问题解答tmux

  • 我在遵循上述说明时犯了一个错误。如果有人可能陷入同样的​​错误,我会分享它:我在自己的计算机的 shell 中而不是远程计算机的 shell 中启动了 tmux。需要在远程计算机的shell中启动tmux。 (21认同)
  • 这个建议帮助我解决了同样的问题,但我认为它包含一个错字。我很确定你需要输入`Ctrl-b`然后输入`d`才能离开/分离`tmux`会话。当然,我的 Ubuntu 12.04 上的 `tmux` 版本就是这种情况。 (8认同)
  • 或者,运行 `tmux detach` 而不是键入 `ctrl-b d` (7认同)
  • 现在正在再次开发屏幕:https://lists.gnu.org/archive/html/screen-devel/2014-04/msg00024.html 你能更新你的答案吗? (6认同)
  • @CraigM 如果您只有一个屏幕会话处于活动状态,请使用“screen -x -r [screenname]”或简称“screen -rx”。这允许您附加现有的屏幕实例。 (4认同)
  • tmux 有一个愚蠢的想法,即调用 free(2) 实际上不应该释放内存,这会导致长时间运行的 tmux 逐渐消耗更多内存,无论它们是否实际执行任何操作。我上次检查时 tmux 拒绝修复这个问题。Screen 支持您列表中的最后 3 个功能(我使用其中的大部分)并且不会泄漏您的所有内存。 (2认同)

cot*_*eyr 447

选项1: nohup

最好的方法往往是最简单的。

nohup long-running-command &
Run Code Online (Sandbox Code Playgroud)

它是专门为此而制作的,它甚至将标准输出记录到nohup.log.

man nohup
Run Code Online (Sandbox Code Playgroud)

选项 2:bg+disown

nohup long-running-command &
Run Code Online (Sandbox Code Playgroud)

如果你想“后台”已经运行的任务,那么Ctrl+Z然后运行bg将你最近挂起的任务放到后台,让它继续运行。disown将在您注销后保持进程运行。该-h标志可防止挂断。


screen其他人可以做到,但这不是他们的目的。nohup对于您知道将要放弃bg的任务,以及您已经在运行且不想重新开始的任务,我建议您使用这些任务。

请记住,两者都是 bash 特定的。如果您不使用 bash,则命令可能会有所不同。

  • 我建议做`disown -h` (8认同)
  • 我需要在 Ubuntu 18 上使用 `disown -a` 而不是 `disown -h`;确保在否认后“jobs”的输出为空,以验证它是否真正被否认。 (6认同)
  • `bg` + `disown` 对我不起作用。我有一个正在运行的部署脚本,我忘记在 tmux 中启动,并且需要提前离开去开会。该脚本不断向 shell 输出进度。`ctrl+z` 停止了进程,让我回到 bash。`bg` 恢复了该过程,但它也恢复了将状态输出到 bash,从而无法看到我正在输入的内容。但是,`disown` 命令产生了“disown: current: no such job” (4认同)
  • 澄清一下,选项 2 是 `bg` + `disown`。`bg` 本身是不够的。如果您注销 ssh,`bg` 或 `&amp;` 可能会起作用(因为默认 `shopt huponexit=off`),但如果您的 ssh 连接断开,则它将不起作用,除非您 `disown` (2认同)

Lin*_*oln 244

你可以通过使用来做到这一点screen

键入man screen以了解更多信息或阅读此屏幕手册页

简单场景:

  • ssh 进入你的远程盒子。输入screen然后开始你想要的过程。

  • Ctrl-A然后Ctrl- D。这将“分离”您的屏幕会话,但让您的进程继续运行。您现在可以退出远程框。

  • 如果您想稍后回来,请再次登录并键入screen -r这将“恢复”您的屏幕会话,您可以看到您的过程的输出。

  • 我通常会使用“screen -S name”命名我的屏幕会话,以便以后更容易连接到正确的会话。 (40认同)
  • 离开前与“screen -S”和回来时“screen -r”的组合真是太棒了! (3认同)
  • 就个人而言,我正在开发一个没有任何包控制软件的盒子。在花了大约半个小时从源代码构建 TMUX 的依赖项(我个人有经验和喜欢)之后,很明显 screen 对我来说是更好、更简单的解决方案。TL;DR:此问题的最佳解决方案取决于用例、机器以及您需要多少时间进行设置。感谢您的回答:) (2认同)
  • 当您希望将来恢复屏幕时,使用“screen -list”列出所有活动屏幕也很有帮助。您可以使用 `screen -r XXXXX` 来恢复 ID 为 XXXXX 的屏幕。 (2认同)

小智 94

Screen 和 nohup 是更好的方法,但是如果您必须分离已经在没有 screen 或 nohup 的情况下运行的进程,您可以运行 disown 命令。

disown [-ar] [-h] [jobspec… |pid… ]

如果没有选项,从活动作业表中删除每个作业规范。如果-h给出该选项,则作业不会从表中删除,但会被标记,以便在 shell 收到 SIGHUP 时不会将 SIGHUP 发送到作业。如果jobspec不存在,并且既-a没有-r提供也没有提供选项,则使用当前作业。如果没有提供jobspec,则该-a选项表示删除或标记所有作业;-r没有jobspec参数的选项将操作限制为正在运行的作业。

使用 disown 您可以关闭终端并使进程在机器上运行。

  • 这也是我最喜欢的做法。我经常使用`disown -a &amp;&amp; exit` (13认同)
  • 一个警告,我用 Ctrl-Z 停止了一个正在运行的进程,并且在调用 `disown` 之前没有在后台启动它,它杀死了它。 (8认同)
  • 如果它想写入终端可能会崩溃。重定向正在运行的进程的输出并不那么容易。最好用 nohup 正确启动它。 (3认同)
  • 这是一个很好的答案,因为它直接回答了问题。问题的作者问*在*已经执行了一堆长时间运行的命令之后要做什么。这些答案中的大多数都让您知道*在*执行命令之前要做什么。 (3认同)

Cha*_*aos 75

我被困在一个很大的 mv 中,所以我无法停止该过程,设置屏幕,然后再次启动它。通过基本上执行以下步骤,我设法退出了 SSH 会话,进程正在运行:

  1. 建立SSH连接: ssh user@host
  2. 运行所需的命令以启动进程
  3. Ctrl+Z暂停该过程
  4. 运行bg将暂停的进程置于后台并恢复它。
  5. 运行disown [pid](进程 ID 是可选的,默认为最后一个进程)以拒绝进程。要获取工作列表,只需输入jobs之前。
  6. 通过运行退出 SSH 会话logout

的用法disown命令:

disown [-ar] [-h] [jobspec ... | pid ... ]
              Without  options,  remove  each jobspec from the table of active
              jobs.  If jobspec is not present, and neither the -a nor the  -r
              option  is  supplied, the current job is used.  If the -h option
              is given, each jobspec is not removed from  the  table,  but  is
              marked  so  that  SIGHUP  is  not  sent  to the job if the shell
              receives a SIGHUP.  If no jobspec is  supplied,  the  -a  option
              means  to  remove or mark all jobs; the -r option without a job?
              spec argument restricts operation to running jobs.   The  return
              value is 0 unless a jobspec does not specify a valid job.
Run Code Online (Sandbox Code Playgroud)

  • 内置的永远是我的第一选择 :) THX (4认同)

Sid*_*aRT 24

您可以使用两个主要程序来维护多个 ssh 连接上的程序和终端状态。它们是 screen(现有的,但不幸的是没有维护。显然现在正在积极开发)和 tmux(更新,积极维护)。Byobu 是一个前端,可以在这些系统之上运行并提供额外的 ubuntu 状态信息。在新安装中,它将使用 tmux 作为后端,如果您安装了较旧的 byobu 和现有配置,它将维护以前的后端,无论是 screen 还是 tmux。

屏风

Byobu 可以通过在基于 Debian 的机器上安装到计算机上:

sudo aptitude install byobu
Run Code Online (Sandbox Code Playgroud)

使用 yum,你可以

su -c 'yum install byobu'
Run Code Online (Sandbox Code Playgroud)

也可以在其他发行版上安装 byobu。

使用byobu

byobu使用 ssh 连接后,您可以通过在主机上运行来启动 byobu 。这将为您提供一个如下所示的外壳:

图片-byobu

您还可以在带有 -X 选项的 Ubuntu 机器上使用 Byobu 终端,并轻松拥有完美运行的 byobu。

用法:

通过键入启动byobu byobu

您可以按 F2 在当前会话中创建一个新窗口,按 F3-F4 在各个窗口之间切换。

关于 byobu 最好的部分是,您不必实际杀死在终端中运行的进程即可离开终端。您可以简单地将 screen/tmux(byobu 的骨架)发送到后台并在您下次来时继续:

  • 要离开 byobu 并使其保持运行(分离),请按 F6。

  • 下次你来的时候,就这样做byobu,你应该回到你原来的地方。

    byobu-分离-附加

您还可以通过byobu -S session1等等创建各种byobu会话。当你回来时,你可以连接到它们中的任何一个。

您可以使用 Byobu 做更多事情。用它!一些权威指南在这里,或在这里


Ric*_*way 19

一旦流程开始,您就无法执行此操作,您需要在运行长时间运行的作业之前进行设置。

您可以使用nohup但现代智慧建议您使用 screen 或 byobu 作为您的登录名,以便您可以分离并保持运行。

Screen 的优点是您可以从一台机器上分离并从另一台机器上重新连接,如果您想检查在工作日结束后运行的长时间运行的进程,这很方便。

这里有一个合理的入门指南来筛选

byobu在带有菜单等的屏幕顶部放置了一个易于使用的界面。这也是较新的 ubuntu 上 screen 的当前实现。F2 启动新端子 F3/F4 来回切换,F6 断开连接。键入 exit 以实际永久结束终端。

  • “一旦流程开始,您就无法执行此操作,您需要在运行长时间运行的工作之前进行设置。” -- 不,您可以使用 `disown` 来实现这一点。请参阅@bassgey 的回答 (14认同)

小智 9

对于我运行了很长时间的单个 shell 脚本,我将登录并使用“&”在后台运行该进程。

例子:

/path/to/my/script &
Run Code Online (Sandbox Code Playgroud)

我已经注销并断开了我的 SSH 会话。当我在一段时间后登录时,脚本仍在执行,正如从脚本中连续收集数据所证明的那样。

  • 是的,我想知道 screen / tmux 如何比这个简单的解决方案更好。 (3认同)
  • @MadsSkjern 的原因是,如果您使用 `&amp;` 运行这样的进程,如果您注销并登录到您的 SSH 会话,该进程仍将*运行*,但是您将无法看到该进程的 *输出* (如果你的脚本回显了一些你不会看到的东西,但如果它写了一个文件,文件就会在那里) (2认同)

小智 8

嘿,虽然我同意屏幕是最有效的选择。你可以使用 vncserver 然后启动进程就可以了。

此外,如果您唯一的兴趣是让进程运行而无需控制它,最重要的是,您不知道您需要关闭会话并且您的进程已经在运行,如果你用 bash 作为 shell

首先,您需要通过键入 Ctrl+Z 后跟 bg %1 将进程发送到后台(数字取决于作业编号,通常为 1,但您可以使用命令作业轻松拉出列表)

最后调用 disown 命令(后跟 jobid ...与 bg 命令相同)

这将删除您的 shell 和后台进程之间的父子关系,防止它在您的 shell 终止时死亡。

  • 这个答案是最好的!为什么每个人都在谈论“屏幕”,问题是在登录后事件,如何保持进程运行,现在登录后但启动它们之前。很好的回答 Jorge,你真的帮了我!:) (2认同)

Zib*_*bri 5

最简单的方法是在后台运行命令&。然后就写:

disown -a
Run Code Online (Sandbox Code Playgroud)