I was curious how this worked so I did some reading which I found interesting. In short, this uses ptrace, which is the same Linux kernel mechanism used by debuggers, to attach to a running process and manipulate the open file descriptors (amongst other things) while it runs. So basically it attaches to the process, and changes stdin (fd 0) and stdout (fd 1) to point to your tmux session stdout and stdin.
This is pretty cool! I had done something similar to connect isolated processes on the fly last year. But never thought to do that with tmux as a target.
It's a nice tool (reptyr), but not particularly convenient to use, requiring several steps to move the process to the background and remembering the PID etc. I do wish this was a more streamlined, standard feature of Unix/Linux shells. Something like a simple integrated "pushproc"/"popproc" command.
Seems not super hard to do. A shell function could do the bg, disown, and use the tmux remote API to start a new window and remotely execute reptyr in it.
Judging from the amount of infrastructure that’s been built around background text-mode processes, job control does half a thing and sucks at it. It’s still mandatory, so I wouldn’t blame people for wanting to streamline the process of disassociating from that half-baked builtin support and substituting it with a replacement mechanism.
The streamlined version is what "screen -d …" does, so it's some kind of standard feature, isnt it?. The only "drawback" I see is that you have to plan ahead to use screen.
When I start long running jobs, I try do start them that way, so I can check on them (and their output in a screen logfile) from anywhere:
I also use tmux beforehand, when I plan ahead. But I think this discussion is about those situations where you didn't plan ahead and still need to somehow keep a process running.
> Take away the ownership from the shell using disown
Interesting. So far, my only ever use of disown was to decouple GUI apps that I launched from the terminal. I do that automatically now, as it's annoying when you forget, close the terminal, and a bunch of apps go away.
Just for curiosity: what was the purpose of "disown"? If I recall correctly, it was used so the shell you used to launch the process didn't kill it using a "hang" signal or something like that. But I made a quick test and my shell doesn't seem to kill the background process launched from it, at least when I quit using ctrl + d.
Behaviour depends on your shell. With Bash, for instance:
> The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. [...] To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Job Control Builtins) or marked to not receive SIGHUP using disown -h.
> If the huponexit shell option has been set with shopt (see The Shopt Builtin), Bash sends a SIGHUP to all jobs when an interactive login shell exits.
As others said, wish this use case had been considered on Unix based OSs. I guess it's a very common issue many people have daily. I don't like to do it but some people have some bashrc or ssh config script to auto attach every session to a tmux session or even docker container.
$ reptyr 10330
Unable to attach to pid 10330: Operation not permitted
The kernel denied permission while attaching. If your uid matches
the target's, check the value of /proc/sys/kernel/yama/ptrace_scope.
For more information, see /etc/sysctl.d/10-ptrace.conf
$
I haven't (yet) looked into how to fix or work around this problem.
> What are the risks in setting ptrace_scope to 0?
> - This restores the old behavior where one process can "trace" another process, even if there is no parent-child relationship.
> - In theory, a piece of malware can use this to harm you/your computer; e.g. it can attach to Firefox and log all of your URLs/passwords, etc. In practice this is extremely unlikely unless you blindly install binary debs from random sites, etc.
> - As far as debugging goes, the 0 settings is in fact required for gdb, strace, etc. to attach to non-children unless you run them with elevated privileges (sudo).
> It’s rare, but sometimes it still happens that I forget to open a tmux or screen session when working with something that is supposed to be quickly done.
There are various ways to get ahead of this problem too if you ssh into a tmux session automatically. There are various ways to achieve this.
I didn't know about reptyr, it's very cool. There were times I wished this was possible, but whenever I searched for a solution I got "It's not possible". Oh well...
Yes! I have a shell function that automatically attaches to an existing tmux session or creates a new tmux session if none exists already, after logging into the remote system via SSH:
Don't you find it painful having your tmux session rooted in your homedir (e.g. for all new windows)? I nearly always need to have it anchored some project working directory.
I have tmux anchored to ~ because I hated new shells inheriting random cwd states. Instead I have a function to cd to "bookmarks" with an easy way to add to it and completion.
I have the following in my ~/.tmux.conf so that whenever I split pane or create a new tmux window, it sets the current working directory of the new pane or window to the same directory in which I was before:
# Open new pane or window with the current directory
bind '"' split-window -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"
bind c new-window -c "#{pane_current_path}"
So although the tmux session is run in my home directory, I only need to change the current working directory to my project directory once and then when I create new panes and windows, they have the project directory as the current working directory.
with appropriate ServerAliveInterval and ServerAliveCountMax settings. It works somewhat nicely with dodgy ssh conncetions too. I'm aware of mosh, but this one even outlives when I put the laptop to sleep. Also mosh doesn't allow X forwarding, and I enable that for sharing the clipboard (yes, I'm aware of the security implications). And if I want to leave something long-running, I can just close the window and reattach later.
One problem of course is that you miss the output of the process from before you took over control. Perhaps shells could be extended to better support this way of using tmux/screen.
By the way another approach is of course to use VNC (e.g. some process started in an xterm at work you can access by opening your entire desktop at home.)
Doesn't really feel like the shell would be the right place to do this, as the shell really has no idea, in most cases, of the output history. The whole idea of the scrollback is in the terminal, so it'd probably be, ultimately, the terminal that is the source of this information.
kitty probably has some abilities to do this easily from the shell, as it has all sorts of abilities to interact programmatically with the scrollback history.
not denying value of the article, it's great, but kinda solved problem for me - for multiple years, 99% of cases the first command after ssh login to server is `tmux attach || tmux` for me. Almost never run anything not in tmux/screen.
In practice I have it via bash alias `tma` , not long command as described. Until I can't bring my .bashrc to particular server of course - there long one, may try your suggestion though
Very cool! I hope this becomes a standard feature of all common Unix OSes. Will have to look at what part of this is architecture specific so it can be properly abstracted.
Pretty cool use of ptrace.