How to close all sessions properly using tmux? - tmux

I am using tmux version 2.7. What is a proper way to close all sessions so that there is no session at all running with tmux?
Any process running inside the session (such as a Rails server or Django server) should be terminated properly, without any of them dangling.

Ether of tmux kill-server or pkill tmux will do it (they have the same effect). All processes inside tmux will be sent SIGHUP by the kernel, what each does with it is up to the individual application.

Related

Making tmux do idle timeouts?

Is there any way to configure tmux to kill an idle session? I connect to a server with:
ssh -t host-name tmux new -A -s session-name
Most of the time, I want tmux to keep the session nailed up even if my ssh connection dies. This protects me against transient issues like my desktop crashing. That is, of course, the reason tmux exists.
But if I've simply forgotten to log out, I'd like the session to get killed after a sufficiently long idle time (say, 24 hours).

Background R console and long running session

this is my situation: I usually run R from within Emacs using ESS into terminal emulator, in my local pc. In my work place we get a new server running R so I would use the remote server via ssh. I connect via ssh and all works well. What I would do is to keep alive the R console while I close my laptop and go home so, from my home I would reconnect to the existing R session.
I tried to put the R console in background using C-q C-z Enter to stop the process but, while I close the ssh connection the proces is killed. No luck using bg & too. I also tried mosh but, also in this case, I get some issue related to the UDP traffic across my work's network. Screen and tmux are not also very useful due to their bad interaction with the Emacs eshell.
In both client and server machine I run Debian 8 xfce.
Is there a way to keep alive the R terminal while closing the ssh connection? Which is your approach to the long R sessions?
EDIT
Finally here and here I found the solutio that I'm looking for. I tried the same approach as in the link above, but using tmux, and I get lots of error. The holy grail is screen. I tried to follow step-by-step that procedure but I get an error from emacs while I try to attach a screen session from within eshell. So I tried to use ansi-term instead of eshell and all works as expected. I can attach and detach the R session. In this way I use the remote server machine only for the computation while the R scripts are in my laptop.
So, this is the work-flow:
ssh to the host server
start screen session
start R
detach screen
exit from the server closing the ssh connection
run emacs as daemon in your local machine and open an emacsclient
instance (not necessary run emacs via emacsclient but I prefer this
way)
open your R script
open an ansi-term (M-x ansi-term)
ssh to the server from ansi-term
attach the screen session (screen -r)
connect the remote R console to the local R script (M-x ess-remote)
to detach from R from within ansi-term use Ctrl-q Ctrl-a d return
Thats it. Now I can run a remote R process using a local R script, closing the connection but leaving open the R console so I can re-attach to it in the future, also from a different IP.
This is one of my favourite topics :) Here is what I do:
Always start emacs as emacs --daemon so that it runs in the background.
Always launch emacsclient -nw (for textmode) or emacsclient -c (in x11/graphical mode) to access the daemonized emacs in the background. I have these aliased to emt and emx, respectively.
Now you are essentially done. You can ssh to that box and resume from whereever you can launch ssh from---which may be a smartphone or browser. And ESS of course allows you to have multiple R sessions. After M-x R I often invoke M-x rename-buffer to align the buffer with the project name or idea I work on.
I combine this further with both
byobu (which is a fancy tmux wrapper available in many distros and on OS X, and originally from Ubuntu) to have shell sessions persist
mosh for places like work and home where my laptop can simply resume
Strictly speaking you do not need byobu or mosh for emacs to persist (as running the daemon takes care of that) but you may want it for all your other shell session.
This setup has been my goto tools for years at work and home.

What is the status of long-running remote R sessions in ESS/Emacs?

I routinely run R remotely and have had great success with RStudio server to do so. However, Emacs/ESS is still preferable in many cases, particularly since I often work on multiple projects simultaneously. What is the start-of-the-art when running ESS/R in emacs when the expectation is that the connection will be broken? To be more concrete, I'd love to run a tmux session in Emacs so that I can connect to a long-running R session running in tmux (or screen). What is the status of ESS/Emacs to support such a scenario? This seems to be changing over time and I haven't found the "definitive" approach (perhaps there isn't one).
I do that all the time. At both home, and work.
Key components:
Start emacs in daemon mode: emacs --daemon &. Now emacs is long-running and persistent as it is disconnected from the front-end.
Connect using emacsclient -nw in text mode using tmux (or in my case, the byobu wrapper around tmux). As tmux persists, I can connect, disconnect, reconnect,... at will while having several tabs, split panes, ... from byobu/tmux.
When nearby -- on home desktop connecting to home server, or at work with several servers -- connect via emacsclient -c. Now I have the standard X11 goodness, plotting etc pp. That is my default 'working' mode.
But because each emacs session has an R session (or actually several, particularly at work) I can actually get to them as I can ssh into the tmux/byobu session too.
Another nice feature is tramp-mode allowing you to edit a remote file (possibly used by a remote R session) in a local Emacs buffer as tramp wraps around ssh and scp making the remote file appear local.
Last but not least mosh is very nice on the (Ubuntu) laptop as it automagically resumes sessions when I am back on the local network at home or work. In my case mosh from Debian/Ubuntu on server and client; may also work for you OS X folks.
In short, works like a dream, but may require the extra step of "disconnecting" emacs from the particularly tmux shell in which you launch. Daemon mode is key. Some of these sessions run on for weeks.
I started working like this maybe half a decade ago. Possibly longer. But using ESS to connect to remote Emacs session is much older -- I think the ESS manual already had entries for it when I first saw it in the late 1990s.
But I find this easier as it gives me "the whole emacs" including whatever other buffers and session I may need.
Edit: And just to be plain, I also use RStudio (Server) at home and work, but generally spend more time in Emacs for all the usual reasons.
More Edits: In follow-up to #kjhealy I added that I am also a fan of both tramp-mode (edit remote files locally in Emacs thanks to the magic that are ssh and scp) as well as mosh (sessions that magically resume when I get to work or back home).

How to stop a process when tmux session is detached

I often have several tmux sessions running at the same time, in most of these sessions I will have a local server running on a port. What I want is to be able to automatically kill this server when detaching from a tmux session and similarly re-start the server when re-attaching.
Is there anything in tmux that makes this easier, it feels like if there was a hook that tmux provided so that you could run a script before the session was detached or reattached that would do the trick but I can't see anything like this in the docs.
Fast forward to 2017.
Today tmux has hooks called client-attached and client-detached that run when clients attaches to the session or detaches from it, respectively.
tmux a # attach most recent tmux session
or
tmux list-sessions # look for the session you want to kill
tmux a -t 0 # attach session named "0"
Once inside the session you want to kill:
[Ctrl]-B x # kill current pane of current session
Do that for all the panes and windows within that session and that should do it.
You could add something like this to your ~/.tmux.conf
shell-command /bin/bash yourhook.sh
This would at least give you some functionality when running tmux, but I'm not sure what you would do about a detach hook...

Tie the life of a process to the shell that started it

In a UNIX-y way, I'm trying to start a process, background it, and tie the lifetime of that process to my shell.
What I'm talking about isn't simply backgrounding the process, I want the process to be sent SIGTERM, or for it to have an open file descriptor that is closed, or something when the shell exits, so that the user of the shell doesn't have to explicitly kill the process or get a "you have running jobs" warning.
Ultimately I want a program that can run, uniquely, for each shell and carry state along with that shell, and close when the shell closes.
IBM's DB2 console commands work this way. When you connect to the database, it spawns a "db2bp" process, that carries the database state and connection and ties it to your shell. You can connect in multiple different terminals or ssh connections, each with its own db2bp process, and when those are closed the appropriate db2bp process dies and that connection is closed.
DB2 queries are then started with the db2 command, which simply hands it off to the appropriate db2bp process. I don't know how it communicates with the correct db2bp process, but maybe it uses the tty device connected to stdin as a unique key? I guess I need to figure that out too.
I've never written anything that does tty manipulation, so I have no clue where to even start. I think I can figure the rest out if I can just spawn a process that is automatically killed on shell exit. Anyone know how DB2 does it?
If your shell isn't a subshell, you can do the following; Put the following into a script called "ttywatch":
#!/usr/bin/perl
my $p=open(PI, "-|") || exec #ARGV; sleep 5 while(-t); kill 15,$p;
Then run your program as:
$ ttywatch commandline... & disown
Disowning the process will prevent the shell from complaining that there are running processes, and when the terminal closes, it will cause SIGTERM (15) to be delivered to the subprocess (your app) within 5 seconds.
If the shell isn't a subshell, you can use a program like ttywrap to at least give it its own tty, and then the above trick will work.
Okay, I think I figured it out. I was making it too complicated :)
I think all db2 is daemon-izing db2bp, then db2bp is calling waitpid on the parent PID (the shell's PID) and exiting after waitpid returns.
The communication between the db2 command and db2bp seems to be done via fifo with a filename based on the parent shell PID.
Waaaay simpler than I was thinking :)
For anyone who is curious, this whole endeavor was to be able to tie a python or groovy interactive session to a shell, so I could test code while easily jumping in and out of a session that would retain database connections and temporary classes / variables.
Thank you all for your help!
Your shell should be sending a SIGHUP signal to any running child processes when it shuts down. Have you tried adding a SIGHUP handler to your application to shut it down cleanly
when the shell exits?
Is it possible that your real problem here is the shell and not your process. My understanding agrees with Jim Lewis' that when the shell dies its children should get SIGHUP. But what you're complaining about is the shell (or perhaps the terminal) trying to prevent you from accidentally killing a running shell with active children.
Consider reading the manual for the shell or the terminal to see if this behavior is configurable.
From the bash manual on my MacBook:
The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP
to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To
prevent the shell from sending the signal to a particular job, it should be removed from the jobs table with
the disown builtin (see SHELL BUILTIN COMMANDS below) or marked to not receive SIGHUP using disown -h.
If the huponexit shell option has been set with shopt, bash sends a SIGHUP to all jobs when an interactive
login shell exits.
which might point you in the right direction.

Resources