1

As stated in the question, I'm trying to better understand sessions, processes, process groups, etc. A few questions that I came across while playing around with tmux.

  1. If I open tmux and run ps, I see two bash processes. If I understand correctly, one bash process corresponds to the parent shell and the second bash process is the one that tmux opened?

  2. If I kill the tmux process, the terminal appears to go back to the parent shell, but then if I run ps again, I see two bash processes. My guess is that this second bash process was the one that tmux opened but that I'm no longer connected to on this terminal? How does this second bash process relate to the first one in terms of process groups and sessions?

  3. How do I kill this second bash process? Running kill with the PID doesn't seem to do anything. Also is there a way to detach my terminal from one shell and switch to the another?

  4. If I were to Ctrl+D with tmux open, both tmux and the second bash process exit properly. Is that because tmux sends a signal to end the bash process before tmux closes? Why does this work better than kill.

I was running tmux from a bash shell on my terminal in macOS. I type tmux from the shell to run it. As soon as tmux opens in the terminal, I run ps. When I get the pid of tmux, I run kill [pid] and then run ps again. I've never configured tmux so I suppose the .tmuxrc file will still be at its default.

2
  • 1
    Where are you running tmux from? What commands are you running exactly? (Where are you typing them, and with what options?) And copy-paste their output. Also if you have any relevant shell aliases (e.g. something that would pass options to ps) mention that. And if you have a .tmuxrc, post it as well. – Gilles 'SO- stop being evil' Oct 20 '20 at 17:07
  • Hey I was running tmux from a bash shell on my terminal in macOS. I type tmux from the shell to run it. As soon as tmux opens in the terminal, I run ps. When I get the pid of tmux, I run kill [pid] and then run ps again. I've never configured tmux so I suppose the .tmuxrc file will still be at its default. – NNNComplex Oct 20 '20 at 17:59
1

Step 1: run tmux

Initially, you have a terminal open, with bash running in it. I'll call this the original bash.

You run tmux from the original bash. Tmux runs two processes: the tmux server and the tmux client. The reason it does that is that you can detach from a tmux session and reattach to it later — this is a core feature of tmux. The tmux client connects to the terminal where the session is attached. The server runs the processes running in the tmux windows. When you detach from a session (C-b d), the client exits, but the server and the processes running in the session keep running. In addition to the two tmux processes, assuming you haven't started a tmux session yet, tmux creates a new session containing one window where it runs your shell: that's the second bash.

At this point, the relevant part of the process tree looks like this:

…
        ├─tmux: server───bash───pstree
        └─xterm───bash───tmux: client

This is from the pstree command on Linux. To get a similar display on macOS, see https://apple.stackexchange.com/questions/11770/linux-ps-f-tree-view-equivalent-on-osx. xterm is the terminal where I ran my original bash, and tmux: client is the tmux client started by running tmux in the original bash. tmux: server is the tmux server that the tmux client started, and its child bash is the second bash, where I ran pstree from.

On Linux, here's the output of ps inside tmux:

    PID TTY          TIME CMD
    108 pts/56   00:00:00 bash
    153 pts/56   00:00:00 ps

By default, Linux's ps only shows the processes that are running on the current terminal. That's why I see. On FreeBSD, and I expect also on macOS (I ran this on a machine where my shell is zsh, that's why it shows zsh rather than bash):

19690  0  Is   0:00.36 /usr/local/bin/zsh
20046  0  I+   0:00.01 tmux: client (/tmp//tmux-1001/default) (tmux)
20049  1  Rs   0:00.06 /usr/local/bin/zsh
20138  1  R+   0:00.01 ps

The reason the BSD ps shows more processes is that by default, it shows processes that are attached to any terminal. (The technical term is processes that “have a controlling terminal”.) It doesn't show processes that are not attached to a terminal at all, such as the tmux server.

To see all the processes involved and to get more information about these processes, let's run ps with a few options. The options to see the relevant data are slightly different on different unix variants. I'll show Linux and FreeBSD; macOS is probably close to FreeBSD but may be a little different. On Linux, here's the output of ps x -o pid,ppid,tty,comm f, filtered to the relevant processes:

    PID    PPID TT      COMMAND
    107       1 ?       tmux: server
    108     107 pts/1    \_ bash
    154     108 pts/1        \_ ps
      3       1 ?       xterm
      6       3 pts/0    \_ bash
    105       6 pts/0        \_ tmux: client

And on FreeBSD, with ps -U $(id -u) -A -o pid,ppid,tty,command -d (on macOS you'll need to remove -d and you won't get the tree presentation) (again filtered; on FreeBSD I'm logged in remotely so the original zsh is in a terminal provided by sshd):

  PID  PPID TTY   COMMAND
19689 19687 -     sshd: gilles@pts/0 (sshd)
19690 19689 pts/0 - /usr/local/bin/zsh
20046 19690 pts/0 `-- tmux: client (/tmp//tmux-1001/default) (tmux)
20048     1 -     tmux: server (/tmp//tmux-1001/default) (tmux)
20049 20048 pts/1 - /usr/local/bin/zsh
20149 20049 pts/1 `-- ps -U 1001 -A -o pid,ppid,tty,command -d

In both case you can see six processes:

  • The terminal emulator that provides pts/0.
  • The original shell, running in pts/0.
  • The tmux client, running in pts/0, started from the original shell.
  • The tmux server. It isn't running in a terminal. Its parent (PPID) is process 1. (This happens because when the tmux client starts the server, it double-forks: it creates a child process which itself creates child process, then exits immediately. When the intermediate process exits, the grandchild becomes orphaned and is therefore adopted by init, which is process 1.)
  • The shell running inside tmux. It's running inside the single tmux window, which is the terminal pts/1.
  • ps running inside the shell inside tmux.

Step 2: kill tmux

You kill the tmux process. But which one? We saw above that there are two. We also saw above that on macOS, ps with no options shows all processes that are running in a terminal. So you saw, and killed, the tmux client. This is equivalent to detaching from the session. The tmux server is still running. That's one of the reasons to use tmux: if the client is killed, for example because the terminal where the client is running goes away, the session keeps running.

Step 3: reattach the session

You can see the existing tmux session with tmux list-sessions. And you can reattach to it with tmux attach. If you have several sessions, you can choose which one to attach to by passing the session number after tmux attach, e.g. tmux attach 0 to attach to the session that tmux list-sessions describes as 0: 1 windows (created …) ….

If you want to kill the session without attaching to it, you can use tmux kill-session. There's even a command tmux kill-server which kills all the sessions.

Step 4: normal exit

When you press Ctrl+D or enter exit in the shell inside tmux, the shell exits. When the main process of a tmux window exits, tmux closes the window. When tmux closes the last window, the session exits.

2
  • Thanks Gilles, the distinction between the tmux: client and tmux: server and how to find them via ps is illuminating. One note though is that my output from running ps -U $(id -u) -A -o pid,ppid,tty,command -d on macOS looks quite different — the -d flag actually filters out the tmux, ps, bash processes. But by running ps -A I can see the relevant processes. In addition, instead of being named tmux: server and tmux: client, they're both just called tmux, but I can identify the server as the one with PPID = 1 . – NNNComplex Oct 22 '20 at 15:21
  • @NNNComplex Ok, thanks for the information. I don't have macOS to check. There's probably a way to see tmux: client/server on macOS but it may require a different column name, maybe comm like on Linux? – Gilles 'SO- stop being evil' Oct 22 '20 at 15:28
0

I'm running Fedora 32 with default settings.

If I open tmux and run ps, I see two bash processes.

tmux itself is a child of bash, however it needs to provide you with an independent shell (that's the whole point of the application - being able to detach sessions), so it spawns another bash instance.

If I kill the tmux process, the terminal appears to go back to the parent shell, but then if I run ps again, I see two bash processes

That depends on how you kill it.

tmux spawns its own child which then spawns a shell.

If you kill the child tmux, the child bash should terminate and you will be left with a single bash process.

If you kill the parent tmux, the child tmux will keep on running with the bash process under it, i.e. you'll get two bash processes.

5
  • ps without options wouldn't show the bash process that tmux ran from: by default ps only shows processes running on the current terminal. But it's not clear from the question whether NNNComplex ran ps, or perhaps ps with options. – Gilles 'SO- stop being evil' Oct 20 '20 at 17:10
  • I assumed he always ran ps fax which is what I use. – Artem S. Tashkinov Oct 20 '20 at 17:12
  • @ArtemS.Tashkinov, I ran kill [pid] from inside the tmux shell. I got the pid from running ps without any flags inside the tmux shell (and I only saw one process, albeit this is on macOS). How can I know whether I was kililng the child or parent tmux process? – NNNComplex Oct 20 '20 at 18:13
  • I've no idea how to view the process tree in MacOS X. In Linux that's ps fax. Looks like it's quite complicated: apple.stackexchange.com/questions/11770/… serverfault.com/questions/324945/… – Artem S. Tashkinov Oct 20 '20 at 19:00
  • So the explanation about ps is that the BSD/macOS ps is not POSIX compliant and displays all processes with a controlling terminal by default, not just the ones on the current terminal. By the way ps -d on FreeBSD is similar to ps f on Linux. – Gilles 'SO- stop being evil' Oct 21 '20 at 23:26
0

The tmux environment is a bit of a special case in regards to understanding sessions, mostly since it's designed to be. Normally, when you kill a process, all of it's children processes are reaped (killed) by the system. (This vastly oversimplifies what's actually happening, and can only really be considered accurate for the sake of end results within your specific context.)

With tmux, that arrangement is turned on its ear. tmux is designed to let you start a shell, then disconnect from that session to log out and log back in later and reconnect to the same session. Thus, it keeps its children alive despite its parent being killed.

In your case specifically, you start with one process, the bash process. That is your current shell. When you invoke tmux, your current shell starts a child called tmux, and tmux automatically starts a child bash of itself. This second bash is where you ran your ps command. When you kill your original shell's tmux, you don't actually kill the tmux session, only that connection to it. Thus, your grandchild shell remains running, in the tmux session, and you're dumped back into you parent shell.

See the tmux man pages for how to connect to an existing tmux session or disconnect from it, as well as how to more effectively use tmux.

5
  • ps without options wouldn't show the bash process that tmux ran from: by default ps only shows processes running on the current terminal. But it's not clear from the question whether NNNComplex ran ps, or perhaps ps with options. – Gilles 'SO- stop being evil' Oct 20 '20 at 17:09
  • Thanks for mentioning this. I ran ps without options. So does that mean that one of the two bash processes I see isn't the parent terminal? It appears to have the same PID. – NNNComplex Oct 20 '20 at 18:01
  • Thanks John, I found your post helpful. By running tmux attach, I was able to reattach to that session and Ctrl+D to properly close that session. Can you if there is a way of closing it without having to first use tmux attach? Why wasn't I able to use kill to end that session? – NNNComplex Oct 20 '20 at 18:10
  • “Normally, when you kill a process, all of it's children processes are reaped (killed) by the system.” No, that's completely wrong. Any automatic killing that happens would be based on the disappearance of the terminal, or on a signal handler in a shell, not on a mere parent-child relationship. – Gilles 'SO- stop being evil' Oct 21 '20 at 11:14
  • Vastly simplified to focus on end results within this context, and admittedly technically not perfect (much like Newton is imperfect about physics), but I dispute the "completely wrong" characterization. – John Oct 21 '20 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.