193

I have a running program on a SSH shell. I want to pause it and be able to unpause its execution when I come back.

One way I thought of doing that was to transfer its ownership to a screen shell, thus keeping it running in there.

Is there a different way to proceed?

Lesmana
  • 27,439
levesque
  • 3,815

9 Answers9

131

You can revoke “ownership” of the program from the shell with the disown built-in:

# press Ctrl+Z to suspend the program
bg
disown

However this only tells the shell not to send a SIGHUP signal to the program when the shell exits. The program will retain any connection it has with the terminal, usually as standard input, output and error streams. There is no way to reattach those to another terminal. (Screen works by emulating a terminal for each window, so the programs are attached to the screen window.)


It is possible to reattach the filedescriptors to a different file by attaching the program in a debugger (i.e. using ptrace) and making it call open, dup and close. There are a few tools that do this; this is a tricky process, and sometimes they will crash the process instead. The possibilities include (links collected from answers to How can I disown a running process and associate it to a new screen shell? and Can I nohup/screen an already-started process?):

85

Using GNU screen is your best bet.

Start screen running when you first login - I run screen -D -R, run your command, and either disconnect or suspend it with CTRL-Z and then disconnect from screen by pressing CTRL-A then D.

When you login to the machine again, reconnect by running screen -D -R. You will be in the same shell as before. You can run jobs to see the suspended process if you did so, and run %1 (or the respective job #) to foreground it again.

  • 52
    I think this doesn't answer the question. The question begins with "I have a program running". This answer assumes it's not running yet… – Anko Apr 16 '15 at 09:25
  • 2
    yes he clearly wrote he wants to get it into a screen session :-) – Florian Heigl Oct 08 '19 at 17:12
  • This doesn't answer the question, or at least it doesn't answer this question which is linked: https://unix.stackexchange.com/questions/171250/how-to-move-a-background-job-from-one-terminal-tab-to-another – user3728501 Jun 11 '20 at 19:26
  • This answer is great, as you need some preparation, if you want to it right, at least the next time – PythoNic Jan 04 '22 at 12:40
76

To move a process between terminals or to reattach a disowned, you can use e.g. reptyr.

l0b0
  • 51,350
jofel
  • 26,758
  • 2
    Yeah that saved it, thanks! I read the author's website how it works better than similar or older tools eg. for ncurses programs. – Marcos Mar 08 '12 at 15:19
  • 8
    This is awesome; it should solve a friend's predicament of constantly losing her work by running it straight in ssh and then needing to get on a train. "Oops, forgot to use screen. Again." – Adam Katz Jan 16 '15 at 05:13
  • 3
    +1 Although the accepted screen answer is of course ideal, it doesn't actually answer the question, which specifically requests a way to move a currently running process to screen or the like. Also see this answer: http://serverfault.com/a/284795 – toxefa Apr 18 '15 at 21:15
  • 2
    Absolute live saver. Allowed me to re-attach to running apt dist-upgrade that was sitting on waiting for user confirmation. – andig Feb 10 '19 at 12:24
  • Can be installed using APT on Debian based distros: sudo apt install reptyr. – Qumber Jul 09 '20 at 10:46
27

My favorite solution is using tmux, you could detach the session, and re-attach it in another terminal.

When you detached from previous session, you can safely close the terminal; later use tmux attach to get back to the session, even if you logged out.

daisy
  • 54,555
24

There's also a small utility called retty that lets you reattach running programs to another terminal.

adamg
  • 341
20

I don't use it regularly, but neercs claims to support this. It's a screen-like program with miscellaneous fancy features like better pane management, but the main thing it offers is the ability to import a process into a pane

Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
13

If you just want to pause it and restart afterwards, you can use kill with STOP or CONT signal.

At first find out the processes PID with

$ ps aux

Then send the signals to that PID listed to the process

$ kill -STOP <PID>

$ kill -CONT <PID>
yunzen
  • 239
11

"injcode" from ThomasHabets seems to be exactly the thing I need:

https://github.com/ThomasHabets/injcode

The injcode program allows arbitrary code to be injected into a running process, whether or not you knew beforehand and were running screen or tmux

From the README:

Example 1: move irssi from one terminal to another

Maybe move it into a screen.

First start irssi in one terminal.

Run injcode in another terminal: $ injcode -m retty

Irssi should now be moved to the second terminal, including having a new controlling terminal.

4

This worked for me:

  1. bg the process
  2. jobs -l find process number
  3. tmux start shell window manager
  4. reptyr -L PROCESSNUMBER

reptyr's -L was necessary to get this to work:

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

because of this error:

$ reptyr 30622

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

And with -L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
the
  • 900