4

I'm trying to find a way to check if tmux server is running or not in order to update my zsh prompt with that information.

when tmux server is alive

> tmux ls
0: 1 windows (created Sat Jul 10 13:47:36 2021) (attached)

so I can grep that output, correct?

grepping that output:

> tmux ls | grep -i "windows"
0: 1 windows (created Sat Jul 10 13:47:36 2021)

windows is colored in red (for me), or whatever color you have in your terminal, so the command worked.

I chose windows because the word will always appear in the tmux ls output.

now checking if the server is offline

After killing the tmux server:

tmux kill-server

now I check to see if server is alive using tmux ls

> tmux ls
no server running on /tmp/tmux-1000/default

normal output, as expected.

The grep seems to fail when when the tmux server is dead; check this strange thing out:

> tmux ls | grep -i "windows"
no server running on /tmp/tmux-1000/default

exit code of this command:

> echo $?
1

meaning that grep failed to grab the output.

another test case showing strangeness

> tmux ls > file.txt
no server running on /tmp/tmux-1000/default

It's always printing no server ... bla bla on the screen, no matter what you run.

When catting the file:

> cat file.txt

nothing there

How do I check if tmux server is running or not in order to update my zsh prompt with that information?

NOTE: variable $TMUX is useless for me, because I don't want to know if I'm in a session while already being in a session, that is pointless. I want to know if the server is alive or dead, no matter if I'm attached to a session or not.

EXTRA (for zsh users only)

if you want to put tmux server status in your zsh prompt here's what i got: enter image description here

to get this just add these lines to your .zshrc

function update_prompt_and_venv () {
  if tmux ls &> /dev/null; then
      tmux_server="%{$terminfo[bold]$fg[black]%}(%{$terminfo[bold]$fg[green]%}tmux%{$terminfo[bold]$fg[black]%}) "
  fi
  PROMPT="
$tmux_server ... $your_cwd
> "
}
precmd_functions+=(update_prompt_and_venv)

contents:

  • a function to be called every time your press enter in terminal
  • a variable with tmux server status
  • the prompt updated in the function
  • make sure you add the function to precmd_functions in order to by called before every entered command

and when you press enter after you closed the server you will see the updates immediately

3
  • 1
    You can check this without using tmux at all, as long as the defaults for the socket path and the socket name don't change. Just check if /tmp/tmux-$(id -u)/default exists.
    – chepner
    Commented Jul 10, 2021 at 21:44
  • 1
    Once you've posted something here, whether it's a question or answer, it's not "yours" any longer and other people can and will edit it to correct grammar, markup, and formatting. They might also insert clarifications that were brought out in comments, reformulate sentences to make the text flow better, etc. They do this in the hope that the question and its answers should be accessible and helpful to as many people as possible.
    – Kusalananda
    Commented Jul 12, 2021 at 14:21
  • 1
    Note that if you have a solution of your own that you'd like to share, then consider adding it as an answer below instead of as an edit to the question. You could even accept the self-answer later if you wish. It's not until an answer has been accepted by you that the question is marked as resolved. See both unix.stackexchange.com/help/someone-answers and unix.stackexchange.com/help/self-answer
    – Kusalananda
    Commented Jul 12, 2021 at 15:59

3 Answers 3

13

Your confusion comes from the fact that tmux, like all other utilities, writes error messages and other diagnostic messages to the standard error stream rather than to the standard output stream. With the > redirection, you only redirect the standard output stream, not the error messages. Likewise, when you pipe the output of a command, you only pipe the standard output stream, not the error messages. This is by design.

However you don't need to grep anything here and can instead rely on investigating the exit status of tmux itself.

There is a has-session sub-command of tmux that exists solely to tell you whether a session exists (or if a specific session exists):

has-session [-t target-session]
(alias: has)

Report an error and exit with 1 if the specified session does not exist. If it does exist, exit with 0.

This means that you could use

if tmux has-session 2>/dev/null; then
    echo session exists
else
    echo no sessions
fi

This relies on investigating the exist status of tmux has-session and does not require parsing the output of the command for specific strings.

We redirect the error stream to /dev/null to discard it using 2>/dev/null. The tmux command will output an error message there if there are no sessions available, but we're not interested in that message.

0
4

tmux ls | grep -i "windows" pipes the stdout of tmux ls into grep. The no server running on /tmp/tmux-1000/default message is being printed to stderr, not stdout.

To grep both stdout and stderr, you have to redirect stderr to the same place as stdout. For example:

tmux ls 2>&1 | grep -i "windows"

or just redirect stderr to /dev/null:

tmux ls 2>/dev/null | grep -i "windows"

BTW, unless you actually need grep's output displayed, you should probably use grep's -q (or --quiet, --silent) option and check grep's exit code. e.g.

tmux ls 2>/dev/null | grep -i -q "windows"

if [ $? -eq 0 ] ; then
  echo "tmux is running for $USER"
else
  echo "tmux is not running for $USER"
fi
0
2

In unix, when a program starts, it has 3 file handless open: STDIN STDOUT SDERR

Redirection with | normally sends STDOUT from the first program to STDIN of the second program. Errors like "no server is running" go to STDERR which typically end up on the terminal instead of in the pipe or other redirection.

If you want to capture both STDOUT and STDERR, you need to do more. In bash, zsh, and newer shells, this would work:

tmux ls |& grep...

In older shells (and current ones), you would need to do this:

tmux ls 2>&1 | grep...

This tells the shell to create the pipe on STDOUT and then replace the STDERR filehandle (2) with a duplicate of the STDOUT (1) file handle before running the first command. Note the order of 2>&1 and | is critical here.

A possibly simpler alternative not involving grep would be to just run tmux ls and then check the output of $? for errors. Although this would not distinguish between other tmux errors. For instance

if ! tmux ls
then
    # do this when tmux errors
fi
1
  • yeah. its working. nice answer
    – alexzander
    Commented Jul 10, 2021 at 11:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .