281

I'm doing some test-runs of long-running data migration scripts, over SSH. Let's say I start running a script around 4 PM; now, 6 PM rolls around, and I'm cursing myself for not doing this all in screen.

Is there any way to "retroactively" nohup a process, or do I need to leave my computer online all night? If it's not possible to attach screen to/nohup a process I've already started, then why? Something to do with how parent/child proceses interact? (I won't accept a "no" answer that doesn't at least address the question of 'why' -- sorry ;) )

ojrac
  • 2,913
  • 3
  • 17
  • 5
  • 5
    Just saw an interesting blog post about `disown`. https://blogs.oracle.com/ksplice/entry/disown_zombie_children_and_the – ojrac Mar 17 '11 at 15:46

13 Answers13

219

If you're using Bash, you can run disown -h job

disown

disown [-ar] [-h] [jobspec ...]

Without options, each jobspec is removed from the table of active jobs. If the -h option is given, the job 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 jobspec is not present, and neither the -a nor -r option is supplied, the current job is used. If no jobspec is supplied, the -a option means to remove or mark all jobs; the -r option without a jobspec argument restricts operation to running jobs.

gharper
  • 5,365
  • 4
  • 28
  • 34
  • Awesome; I was hoping something like this would turn up. – ojrac Jun 12 '09 at 00:13
  • 8
    Life can be unfair. gharper and me were posting this at about the same time :) – Martin M. Jun 12 '09 at 07:02
  • Sorry for revoking the "answer" cred, but damn... a good one came up. I don't feel too bad, though; you're already at +12 from this ;) – ojrac Jun 12 '09 at 14:36
  • Totally agree - I'm going to have to play with that grab.c program a bit. Looks very cool! – gharper Jun 12 '09 at 17:03
  • 4
    You are my hero – Thomas Dignan Jul 09 '10 at 01:42
  • 9
    disown is not specific to bash. It's also in zsh, ksh93, ... – Phil P Jan 17 '11 at 10:18
  • thanks @gharper it works like a treat. I've got a process that was already running i estimate will take over 5 hours to complete and I can't be here to babysit it. – Matthew Setter Apr 18 '12 at 15:36
  • Is the `jobspec` the same as the process `pid`? – Shoan May 01 '12 at 15:23
  • No, jobspec is different from proc id... there's a good overview of bash job control here: http://www.linuxselfhelp.com/gnu/bash/html_chapter/bashref_6.html – gharper May 01 '12 at 16:14
  • 3
    I found that you actually have to use `disown %1` if 1 is the jobspec, unlike fg or bg where you just use `bg 1` http://www.serverwatch.com/tutorials/article.php/3935306/Detach-Processes-With-Disown-and-Nohup.htm – mltsy Apr 09 '13 at 17:21
  • 1
    I tried this, but the program will die the first time it writes to `stdout`. You need to use `reptyr` - see Jonathan Tran's answer – Rich May 23 '13 at 16:34
  • @Rich, so http://stackoverflow.com/a/625436/819417 won't work? – Cees Timmerman Jun 17 '15 at 15:16
  • @CeesTimmerman no, in the case where you start a process (without using `screen`) and then want to log out of SSH, `disown` won't cut it, and `reptyr` is needed. I tested that on RHEL in 2013; perhaps things are different now (seems unlikely though). – Rich Jun 17 '15 at 16:25
86

Use reptyr

From the README:

reptyr - A tool for "re-ptying" programs.
-----------------------------------------

reptyr is a utility for taking an existing running program and
attaching it to a new terminal. Started a long-running process over
ssh, but have to leave and don't want to interrupt it? Just start a
screen, use reptyr to grab it, and then kill the ssh session and head
on home.

USAGE
-----

  reptyr PID

"reptyr PID" will grab the process with id PID and attach it to your
current terminal.

After attaching, the process will take input from and write output to
the new terminal, including ^C and ^Z. (Unfortunately, if you
background it, you will still have to run "bg" or "fg" in the old
terminal. This is likely impossible to fix in a reasonable way without
patching your shell.)

A few blog posts by its author:

Jonathan Tran
  • 981
  • 6
  • 5
  • I'm going to stick with built-in tools (i.e. disown), but it's not as flexible as reptyr. +1 – ojrac May 23 '11 at 15:19
  • https://github.com/nelhage/reptyr/issues/54 (Maybe `-T` would have helped. Only learned about it after failed attempt.) – Joachim Wagner Apr 13 '22 at 14:01
24

To steal a process from one tty to your current tty, you may want to try this hack:

http://www.ucc.asn.au/~dagobah/things/grab.c

It needs some reformatting in order to compile to current Linux/glibc versions, but still works.

Juliano
  • 5,402
  • 27
  • 28
18

When a process starts, STDIN, STDOUT and STDERR are connected to something. Generally you can't change that once the command is started. In the case you're describing, that's probably a tty associated with the ssh session. nohup pretty much just does ...

command < /dev/null > nohup.out 2>&1

That is, sets STDIN to /dev/null, STDOUT to a file and STDERR to STDOUT. Screen does much more sophisticated things involving setting up ttys that direct to itself.

I don't know of any way to retroactively nohup or screenize a running process. If you cd to /proc/$pid/fd and see what 0, 1 and 2 point to.

You might have some luck with disown, but not if the process tries to do anything with STDIN, STDOUT or STDERR.

Jeff Atwood
  • 12,994
  • 20
  • 74
  • 92
freiheit
  • 14,334
  • 1
  • 46
  • 69
  • 2
    +1 for the good comments. st(din|out|err) is the other half of the problem, and I appreciate the advice on where to start looking, next time I'm in this jam. – ojrac Jun 12 '09 at 03:25
  • 7
    You actually can change it on most Unixes. It's a disgusting hack. I love it. :) What you do is, connect to the process using debug support like ptrace, then force the process to call dup2() to reconnect 0,1,2 to another filehandle. – Zan Lynx Jun 16 '09 at 20:07
  • 3
    yeah, you can change it. Involves pausing the process (SIGSTOP), and modifying the file descriptors for fd 0, 1, 2. Then restarting (SIGCONT). – Michael Martinez Oct 16 '13 at 00:53
13

I can only give you a simple "No" without the why for the screen part, I'd be interested in the reason myself thou.

However have you tried disown (a bash builtin)

~ $ echo $SHELL
/bin/bash
~ $ type disown
disown is a shell builtin
~ $ help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.
Martin M.
  • 6,428
  • 2
  • 24
  • 42
13

Cryopid is a further development from the author of grab.c that freezes a process to a file, which you then run (inside screen) to resume the process.

TRS-80
  • 2,564
  • 17
  • 15
  • 1
    Nice! I tried to use cryopid in my master's dissertation about process migration, but it failed to work all the times, no matter what I did. In the end, I had to use dynckpt with an ancient version of Linux. Are you perhaps involved in the development of cryopid? I see that your name is similar to the author's domain. – Juliano Jun 14 '09 at 18:43
  • 1
    I'm not involved in the development, I just know the author from university. He doesn't have the time to maintain cryopid at the moment, so it looks like some people started working on it at http://sharesource.org/project/cryopid/ – TRS-80 Jun 14 '09 at 19:10
10

nohup on Solaris/OpenSolaris has a -p flag to nohup a running process - for instance, see the Solaris 10 nohup man page.

alanc
  • 1,500
  • 9
  • 12
5

I recently saw a link to neercs, which is a screen-like utility built using libcaca, a colour ascii-art library. Amongst other features, it boasts the ability to grab an existing process and re-parent it inside your neercs (screen) session.

I've not used it however, so I cannot comment on whether it works or not.

Daniel Lawson
  • 5,426
  • 21
  • 27
2

I'm probably under-thinking this so feel free to correct me (I already learned about disown!)... Wouldn't a ctrl-Z and "bg" work to at least get the process running in the background? Or is the key issue that you'd still want to see STDOUT while it runs?

Chris_K
  • 3,434
  • 6
  • 41
  • 45
  • 1
    That would still kill the process when the owning tty dies so the OP needs to leave the box where he intiated the command running, which is what he wants to avoid – Martin M. Jun 11 '09 at 23:11
  • OK I'll buy that. Thanks for the explanation. So the disown -h suggestions sure look a lot smarter than mine :-) – Chris_K Jun 11 '09 at 23:15
  • 1
    You could still do this, just after you'd have to disown -h: http://stackoverflow.com/a/625436/705198 – AndrewPK Jan 26 '12 at 20:47
2

If you can live with not being able to interact with the process and you don't object to loading random kernel modules, you could do worse than to look at Snoop. Alternatively, there are a couple of other projects. Here is one call injcode, which can mostly do what you want to do.

David Pashley
  • 23,151
  • 2
  • 41
  • 71
2

You can redirect process output to file with gdb

https://blog-en.openalfa.com/how-to-detach-from-the-terminal-a-running-process-in-linux

and then disown it

Upd: I had to run gdb with sudo and slightly different gdb command in Ubuntu 18.04:

p (int)dup2(open("/tmp/test.stdout", 1), 1)

d9k
  • 123
  • 1
  • 7
1

I wanted to use nohup (or similar) to start the links command-line browser and to attach to it after to download a file from ASP.NET website with complicated authentication process and a lot of hidden view state that made it difficult to use do the job with curl/wget.

I finally ended up using tmux which solved the job just great:

  1. Run tmux
  2. Run your app (links in my case) and leave it running
  3. Close SSH session, the app will remain running
  4. Connect with SSH to the same machine later and run tmux attach to bring the app back to screen
Dmitry Gusev
  • 111
  • 3
  • tmux is great -- but, like nohup or screen, it only works if you use it before starting your process. This question is about the times when you realize you need tmux after your process is already running. – ojrac Aug 18 '17 at 16:57
-1

Is it that you're worried about the session timing out? In that case you could Ctrl-z and bg the process, and then just put somthing to keep the session alive like a "ping -t localhost" or "top".

If it's that you want to logout, then I'm afraid I can't add to the other comments.

TrojanName
  • 155
  • 1
  • 2
  • 7