如何放弃正在运行的进程并将其关联到新的屏幕外壳?


159

我在SSH Shell上有一个正在运行的程序。我想暂停它,并在我回来时能够取消暂停它的执行。

我想到的一种方法是将其所有权转移到屏幕外壳,从而使其在其中运行。

还有其他方法可以进行吗?


8
另请参阅是否可以对已启动的进程进行nohup /筛选?和在恢复的SSH会话中运行的Resume命令,其中提到了(目前)此处未提及的几种基于ptrace的解决方案。
吉尔斯(Gilles)2010年

从诸如unix.stackexchange.com/a/4039/13496之类的问题中,我听到了有关rettyneercs的信息。嗯...想知道在下次运行进程之前是否有像“ screen here”这样的层,将来是否应该失去顶级终端,这将使您很容易恢复到stdin / out / err
Marcos

我不能理解的这个问题中的次要/隐性问题是...为什么在后台有一个更新的/刚刚发布的甚至不需要/等待stdin的情况,shell为什么选择放弃暂停的工作?这是我已经习惯的治疗方法,所以不知道这里发生了什么……
Marcos

Answers:


86

使用GNU screen是您最好的选择。

首次登录时开始运行屏幕-我运行screen -D -R,运行命令,然后使用断开连接或将其挂起CTRL-Z,然后按CTRL-Athen 断开与屏幕的连接D

当您再次登录计算机时,通过运行重新连接screen -D -R。您将和以前一样在同一外壳中。jobs如果这样做,您可以运行以查看挂起的进程,然后运行%1(或相应的作业#)再次将其挂起。


2
哇,我不敢相信GNU Screen的答案是目前评分最低的。我想念什么吗?
Faheem Mitha

1
也许!对我来说似乎是最好的。
Andrew Yochum

1
回顾过去,它显然是最轻松的解决方案,只要您可以进行相应的计划并在屏幕环境中启动流程即可。无论如何,我把它作为正式答案!
levesque 2012年

28
我认为这不能回答问题。问题开始于“ 我正在运行程序 ”。这个答案假设它尚未运行……
Anko 2015年

是的,他清楚地写道,他想让它进入银幕环节:-)
Florian Heigl

112

您可以使用disown内置命令从外壳中撤消程序的“所有权” :

# press Ctrl+Z to suspend the program
bg
disown

但是,这仅告诉Shell SIGHUP在退出时不要向程序发送信号。该程序将保留与终端的任何连接,通常作为标准输入,输出和错误流。无法将它们重新连接到另一个终端。(屏幕通过模拟每个窗口的终端来工作,因此程序会附加到屏幕窗口。)


通过将程序附加到调试器中(即使用ptrace)并使其调用和open,可以将文件描述符重新附加到其他文件。有一些工具可以做到这一点。这是一个棘手的过程,有时它们会使该过程崩溃。可能性包括(从答案收集的链接到我如何放弃正在运行的进程并将其关联到新的屏幕外壳?以及是否可以对已经启动的进程进行nohup /筛选?):dupclose


disown从作业控制列表中删除该过程。
ctrl-alt-delor

3
为什么不disown -h呢?
Cees Timmerman 2015年

@CeesTimmerman将工作留在shell的工作表中,但是这样做的好处是什么?
吉尔斯2015年

@Gilles:所以你仍然可以fgkill它,看它是否在其自己的目的。
彼得·科德斯

提到的实用程序可用于一组流程(例如bzcat a.bz2 | grep text)?Man for reptyr表示它不支持将过程与孩子一起移动。
dma_k 2015年

64

要在终端之间移动进程或重新挂接未使用的进程,可以使用例如reptyr


1
是的,保存了它,谢谢!我在作者的网站上读到了它比类似或更旧的工具更好的工作方式。对于ncurses程序。
马科斯(Marcos)

4
这太棒了; 它应该解决朋友经常通过ssh直接运行它然后需要上火车而失去工作的困境。 “糟糕,忘记使用屏幕了。再次。”
亚当·卡兹

3
+1尽管接受的screen答案当然是理想的,但实际上并不能回答问题,后者特别要求当前正在运行的进程移至screen或类似的方法。另请参阅以下答案:serverfault.com/a/284795
toxefa

1
绝对的救星。让我重新连接到正在等待用户确认的apt dist-upgrade上。
andig

28

我最喜欢的解决方案是使用tmux,您可以分离会话,然后将其重新连接到另一个终端。

与上一个会话分离时,可以安全地关闭终端。以后tmux attach,即使您已注销,也可以使用它返回会话。


1
您还可以与您的朋友分享会话,并使用多个窗口和窗格等等!喜欢它^ _ ^
igor

请使用示例?
Vitaly Zdanevich '16

21

还有一个名为retty的小实用程序,可让您将正在运行的程序重新连接到另一个终端。


19

我不经常使用它,但neercs声称支持这一点。这是一个screen类似程序,具有多种花哨的功能,例如更好的窗格管理,但是它提供的主要功能是能够将过程导入到窗格中


2
有趣。它的确发挥了肮脏的作用(ptrace),但它不仅操作文件描述符,还分叉了该过程。它可以抓取find /,但使交互式bash崩溃了。
吉尔斯(Gilles)2010年

@吉尔斯(Gilles)我不记得我尝试过的情况如何,但是它的声誉不高,有人告诉我它经常失败
迈克尔·莫罗泽克

9

如果您只想暂停它并随后重新启动,则可以使用killwith STOPCONTsignal。

首先找出与

$ ps aux

然后将信号发送到该进程列出的PID

$ kill -STOP <PID>

$ kill -CONT <PID>

9

ThomasHabets的“ injcode”似乎正是我需要的东西:

https://github.com/ThomasHabets/injcode

injcode程序允许将任意代码注入正在运行的进程中,无论您是否事先知道并正在运行屏幕或tmux

从自述文件:

示例1:将irssi从一个终端移到另一终端

也许将其移到屏幕上。

首先在一个终端中启动irssi。

在另一个终端中运行injcode:$ injcode -m retty

Irssi现在应该移到第二个终端,包括拥有一个新的控制终端。


1

这为我工作:

  1. bg 过程
  2. jobs -l 查找过程号
  3. tmux 启动外壳窗口管理器
  4. reptyr -L PROCESSNUMBER

reptyr-L必要得到这个工作:

-L Like '-l', but also redirect the child's stdio to the slave.

由于此错误:

$ reptyr 30622

[-] Unable to open the tty in the child.
Unable to attach to pid 30622: Permission denied

和-L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.