159

I am trying to figure out how to attach to a tmux session if a named tmux session exists, if not I want to create a new one with the given name.

Currently, I know of a few tmux commands which can partly achieve what I am looking for, but its not clear how to combine them together to get what I am looking for:

  • tmux attach attaches to an automatically existing session - but errors out if no session exists
  • tmux new creates a new session - but it does so every time, so I can't leave it in my .tmux.conf
  • tmux has-session tests whether a session exists - but I don't know how to stitch it together with the other commands

Thus, I would like to create a tmux script, so that this happens automatically, instead of having to manually create it everytime I need to log into a sessions.

How can I write a automatic script so as to create a new tmux session (if a given session name doesnt exist) or attach to a session name (if it exists)?

alpha_989
  • 4,882
  • 2
  • 37
  • 48
rampion
  • 87,131
  • 49
  • 199
  • 315
  • 15
    @kzh: I view it as a programming tool question, like vim – rampion Jan 21 '11 at 18:46
  • 6
    I have written another possible answer for this question as a gist, in case anyone's interested: https://gist.github.com/chakrit/5004006 – chakrit Feb 21 '13 at 11:22
  • 10
    Meanwhile, my `man tmux` says: "The -A flag makes new-session behave like attach-session if session-name already exists" – Petr Viktorin Nov 18 '13 at 13:13
  • 1
    For those flagging to move this, I should note that even moderators cannot migrate questions more than 60 days old to another site. The reasons for this system limit are explained [here](http://meta.stackexchange.com/questions/151890/disable-migration-for-questions-older-than-60-days). – Brad Larson Feb 21 '17 at 03:22
  • https://gist.github.com/MohamedAlaa/2961058 find list of all commands – ULLAS K Mar 16 '17 at 18:31
  • 1
    @BradLarson, currently, the best/simplest option to do this is answered in a comment, way down: https://stackoverflow.com/questions/3432536/create-session-if-none-exists#comment74258862_7799360. Most users who come here wont be able to find this. This is obviously a very important question as you can see by the number of votes. Is it possible to open this question, so I can add that as an answer, so new people can find this? – alpha_989 Mar 06 '18 at 13:33
  • @alpha_989 - I've reopened it. Feel free to leave a new answer. – Brad Larson Mar 06 '18 at 15:11
  • 1
    related: https://unix.stackexchange.com/questions/103898/how-to-start-tmux-with-attach-if-a-session-exists – Ciro Santilli OurBigBook.com Apr 03 '19 at 14:25

8 Answers8

170

I figured it out (and had it pointed out to me).

tmux attach || tmux new
rampion
  • 87,131
  • 49
  • 199
  • 315
  • 29
    This answer works better for me because I can name the session: `tmux attach-session -t my-session || tmux new-session -s my-session`. The only problem is this is not atomic. tmux really ought to have a create-or-attach command. – Andrew May 11 '12 at 20:19
  • 5
    I have next alias in bash - `alias tm='tmux attach || tmux new'` – azat Apr 17 '13 at 19:51
  • 10
    Upvoting because with a small tweak this works with named sessions: `tmux attach -t some_name || tmux new -s some_name`. Change some_name to $1 add a shebang, and save. – Cheezmeister Jan 09 '14 at 04:48
  • @RandalSchwartz, yes - why `new-session` is better? – anatoly techtonik Feb 05 '14 at 13:00
  • I think both answers are good for different use cases. I modified this to not output any error messages with attach: `(tmux has &>/dev/null) && tmux attach || tmux new`. I currently use both answers in different environments. – daboross May 11 '14 at 18:41
  • 11
    Note to those unfamiliar with tmux and wondering about `new` vs `new-session`: they are synonyms, and so are `attach` and `attach-session`. – Esteis Jul 24 '15 at 08:38
  • 1
    `tmux new-session -ds default \; split-window -dv 2>/dev/null; tmux attach -t default` works far better and does not open a second tmux in case you `/bin/kill` the first one. The only downside is that you need to name the sessions for this. – Tino May 25 '16 at 16:05
  • @rampion, the link doesnt seem to be working.. also a better solution maybe available here: https://stackoverflow.com/questions/3432536/how-to-create-new-tmux-session-if-none-exists?noredirect=1#comment74258862_7799360 – alpha_989 Mar 06 '18 at 15:55
  • Someone who met a unexpected error to run this command with tmux 3.2 can try `tmux a || true && tmtux n`, which is more robust. – Chang Ye Jul 18 '20 at 15:55
93

Alternately, you can add

new-session

to your .tmux.conf - that will create a default session on server start.

Then tmux attach will either attach to the current session (running server, that is), or create a new session (start the server, read the config file, issue the new-session command) and attach to that.

Leonid Shevtsov
  • 14,024
  • 9
  • 51
  • 82
91

As pointed out in comments from Petr Viktorin, jkoelker and pjincz, you can use the following command to attach to mySession if it exists, and to create it if it doesn't:

 tmux new -A -s mySession

From man tmux:

new-session[-AdDEP] [-cstart-directory] [-Fformat] [-nwindow-name] [-ssession-name] [-tgroup-name] [-xwidth] [-yheight] [shell-command]

(alias: new)

Create a new session with name session-name.

[...]

The -A flag makes new-session behave like attach-session if session-name already exists; in this case, -D behaves like -d to attach-session.

new-session has supported -A since tmux-1.8.

rampion
  • 87,131
  • 49
  • 199
  • 315
alpha_989
  • 4,882
  • 2
  • 37
  • 48
  • 1
    If you are going to use this in something like `gnome-terminal` as the command I'd suggest leaving off the `-s` and the specific session name so you don't end up with EVERY new `gnome-terminal` session attached to the same session. You can always select an existing session with `prefix + s` after opening a new terminal. – dragon788 Jul 04 '18 at 03:58
15

Adapting Alex's suggestion to include project based configuration upon startup, I started using the following:

# ~/bin/tmux-myproject shell script
# The Project name is also used as a session name (usually shorter)
PROJECT_NAME="myproject"
PROJECT_DIR="~/myproject"

tmux has-session -t $PROJECT_NAME 2>/dev/null
if [ "$?" -eq 1 ] ; then
    echo "No Session found.  Creating and configuring."
    pushd $PROJECT_DIR
    tmux new-session -d -s $PROJECT_NAME
    tmux source-file ~/bin/tmux-${PROJECT_NAME}.conf
    popd
else
    echo "Session found.  Connecting."
fi
tmux attach-session -t $PROJECT_NAME

where tmux-myproject.conf is my startup series of tmux commands to create my windows and panes, as well as start my editors.

Anm
  • 3,291
  • 2
  • 29
  • 40
14

Although I find rampion's answer is sufficient for using 1 session, this script lets you setup multiple sessions:

SESSIONS="work play"

function has-session {
    tmux has-session -t $1 2>/dev/null
}

function except 
{
    if [ "$?" -eq 1 ] ; then
        $1
    fi
}

# Configure your sessions here
function session-work
{
    tmux new-session -d -s work
    tmux neww -k -t work:1
}

function session-play
{
    tmux new-session -d -s play
    tmux neww -k -t play:1
}

#
#MAIN 
for x in $SESSIONS
do
    echo $x
    has-session $x
    except session-$x
done

NOTE:

-k  --> new-window will not be created if already exists
-d  --> start session or window, but don't attach to it yet
-s  --> name the session
-t  --> specify a target location in the form session:window.pane 
Alex Gaudio
  • 1,894
  • 1
  • 16
  • 13
9

I use an alias to create a new session if needed, and attach to my default session if it already exists:

alias tmuxre='tmux new-session -t default || tmux new-session -s default'

I added this to my .login on my server.

The reason I do it this way is because I don't want to attach to the same actual session, I want a new session which uses the same group of windows.

This is also similar to running screen -xRR.

Dakusan
  • 6,504
  • 5
  • 32
  • 45
Michael
  • 776
  • 6
  • 13
  • 2
    If you are in and out of your session often, this leaves lots of unused sessions, as seen by `tmux list-sessions`. – Anm Aug 16 '12 at 19:09
  • Yeah, it does, I just clean them up every now and then. It's a minor drawback to get the functionality I want. – Michael Aug 23 '12 at 21:49
  • Hey @mateusz-piotrowski - I agree with the edit to wrap my code in a code block but why would you edit the other text to be different than what I said? Sorry to comment here but I didn't see anywhere else to. – Michael Jan 25 '16 at 23:02
  • I didn't mean to offend you. I just thought you couldn't _run_ an alias _in_ a config file and so it must have been a typo. – Mateusz Piotrowski Jan 25 '16 at 23:08
  • Proper grammar/phrasing or not, I would hope that if user content is going to be edited on this site, there is some discussion with the user involved, as it seems very heavy-handed and easy to abuse otherwise. I didn't see any way to participate in this process myself, you just arbitrarily decided what I must have meant and changed what I said without bothering to ask for clarification. – Michael Jan 26 '16 at 21:39
  • 3
    By now, you can just type: `tmux new -A -s default` to launch a new session if it is not exist or attach automatically. I think it's much better than editing config file. – pjincz Apr 25 '17 at 07:56
  • @pjincz - that doesn't do what I wanted. That just makes a single session, whereas I wanted multiple sessions connected to the same window set. – Michael Apr 25 '17 at 21:12
2

For those who want to do the same thing in fish:

tmux attach -t mysesh; or tmux new -s mysesh
tinyspark
  • 51
  • 3
0

(edit: A solution considering named sessions is mentioned at the end of this answer)

I came across this question when I was looking for a particular use-case, but couldn't find any solutions to it, so I'll add mine here:

Upon terminal-launch tmux should:

  • check whether there are any unattached sessions and use the first it can find (each session will be attached only once)
  • if there are no unattached sessions create a new one

After reading through the tmux man-pages and looking up arrays in bash I was able to come up with the following one-liner:

 tmux attach -t ${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[1]} || tmux new

Explanation:

  • tmux attach -t $A: attach to session with content of variable A (in our case the return value of the list-session command + array-index call)

  • tmux new: create new session

  • together -> tmux attach -t $A || tmux new: if tmux attach fails, create a new session

The next part (our $A) is finding an unattached session:

  • A = ${$B[1]}: return the second element in the list B (first one seems to always be an empty string)
  • B = tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}'
    • tmux list-sessions: list all sessions
    • tmux list-sessions -F '#{session_name}: -F stands for format and -F '#{session_name}' tells tmux to only show the name of the session and nothing else when it outputs the list
    • tmux list-sessions -f '#{==:#{session_attached},0}': -f stands for filter and -f '#{==:#{session_attached},0}'tells tmux to show only those list-elements, where the session_attached-value is equal to 0
    • tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}': both flags in combination will output only the session name and only for those elements of the list, where the session_attached-value is equal to 0 (=unattached sessions)

Example:

My application was for WSL, so I added it to the launch of my Ubuntu profile inside the settings.json of Windows Terminal:

"commandline": "C:\\Windows\\system32\\wsl.exe -d Ubuntu-22.04 tmux attach -t ${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[1]} || tmux new",

Edit: If you have ([a-zA-Z]) named sessions you can sort the list to put those at the beginning: tmux attach -t ${$(sort -n <<<"${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[*]}")[1]} || tmux new

If you add tmux new -s "primary" || at the beginning of the previous command it will try to create the session with the name "primary" and if it already exists it will only attach to it if it is still unattached, otherwise it will take another unattached session (prioritizing named over unnamed) or just create a new unnamed session if there are no unattached sessions left.

Caveat: each time you run this command and "primary" already exists it will output an error-message that it wasn't able to create a session called "primary" (only visible for a split second)

edit edit: you can redirect those messages by using &> /dev/null:

(tmux new -s primary || tmux new -s secondary || tmux new -s tertiary)  &> /dev/null || tmux attach -t ${$(sort -n <<<"${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[*]}")[1]} || tmux new"