How do I change the starting directory of a tmux session? - linux

The directory where a tmux session is started in will be the directory that new windows start at. How do I change this starting directory without closing the tmux session?

The way to do this is to detach from the session (^b d with the default keybindings) and then specify a different directory when you reattach to it. When attaching to a session, use the -c flag to specify the working directory. Here's an example:
$ tmux list-sessions
tmuxwtfbbq: 3 windows (created Tue Apr 5 14:25:48 2016) [190x49]
$ tmux attach-session -t tmuxwtfbbq -c /home/chuck/new_default_directory
This setting will be persisted - after you've reset the working directory, you won't need to keep specifying it every time you reattach to the session.
For the record, I'm on tmux version 2.0 (though I don't think it matters - I couldn't find anything about adding a -c option to the attach-session command in the change logs so I assume it's been there for quite a while).

Chucksmash's answer is a good one, but it can also be achieved without using the session if you like. The command attach-session is also available in the tmux command prompt; and the target session can be specified as the "current" session using a dot.
attach-session -t . -c /path/to/new/directory

Here's how you can change the tmux session's working directory without detaching the session, and without needing use to the <prefix> keystrokes:
(Option 1) Enter the directory at tmux command prompt:
tmux command-prompt "attach -c %1"
...will open a command prompt, then you type the working directory you want ~/my/dir and press ENTER
(Option 2) Provide the directory on the in-pane command line:
# Execute this in one of the shell panes of within your tmux session:
tmux command-prompt -I $PWD -P "New session dir:" "attach -c %1"
With this approach, the prompt for new-directory is pre-populated with the current dir of the pane which launched the command. Of course you can substitute anything else for $PWD if you please.
Want a shell function?
I have added this to my shell initialization:
# Change the current directory for a tmux session, which determines
# the starting dir for new windows/panes:
function tmux-cwd {
tmux command-prompt -I $PWD -P "New session dir:" "attach -c %1"
}
With all of these options, any future new windows will start in the given dir.
Note: attach, attach-session, and a are all aliases for each other. The tmux command-prompt has many other powers, it's worth reading the man page

use attach-session -c from command prompt or in a binding.
I have bindings to use the current directory automatically, using the provided pane_current_path var.
I have this bound to M-c, to update the current path.
# tmux.conf
# set default directory for new windows in this session to current directory:
bind M-c attach-session -c "#{pane_current_path}"
Similarly, when I just want another window in the current directory without changing the default, I have a binding on C:
# tmux.conf
# open a new window in the current directory
bind C new-window -c "#{pane_current_path}"
My bindings:
c: open a new window in session default directory [default binding]
C: open a new window in current directory
M-c: set session default directory to current directory
Happy Tmuxing!

The default working directory can be changed from the command line like this:
TMUX= tmux -C attach -c directory -t session </dev/null >/dev/null
Compared to command-prompt, for example, this has the advantage that no interactive prompts or confirmations are produced, so this can be run in a script. Unsetting TMUX allows attaching from inside a session, the option -C turns on control mode for non-interactive use and redirecting from /dev/null causes the client to detach immediately, while still updating the default directory. Redirecting the output is not necessary, but it suppresses messages.

Related

Reattached tmux session not importing ~/.bashrc

I am using iTerm2 integrated with tmux. My normal working pattern is to first open up the iTerm2 terminal on my Mac, and then ssh to my dev Virtual Machine.
My dev VM has tmux installed, so that I can re-attach the tmux sessions to my dev VM.
The problem is when the first time I create the tmux session it will source ~/.bashrc with no problem.
But if I clean detach tmux session, and later re-attach those tmux sessions, the ~/.bashrc will not be sourced.
I have included
if [ -f ~/.bashrc ]; then source ~/.bashrc; fi
in ~/.bash_profile, .profile, .bash_login.
And also included
set-option -g default-command "exec /bin/bash"
to ~/.tmux.conf
As is implied by the verb "re-attach", your tmux session (and with it the Bash shell that runs in it) is kept running on your dev machine when you disconnect, so that you can later reconnect to the very same session. (That's the main feature of tmux: Normally, a shell is directly connected to your terminal or SSH session, so when you close / disconnect it, the shell has nothing to read from and output to, so it will have to exit. tmux provides a virtual terminal in between, so the shell has something to hang onto (even if nobody sees the output and nobody currently inputs anything), and tmux handles the session management.)
Applications (like Bash and also Vim) usually only read their configuration on startup. As Bash is kept running (you can verify that via ps -o etime --pid $$), it won't notice that you're reconnecting via tmux, and has no reason to reload its config - everything should still be defined and preserved within the tmux session. If you need to reload a (changed) configuration, you have to do this explicitly (source ~/.bashrc), or open up a new shell.

Can one configure Tmux to load ~/.bashrc instead of ~/.bash_profile?

Right now, when I log in to Tmux, only ~/.bash_profile gets loaded.
I'd like ~/.bashrc to get called instead.
Is that possible?
You can fix that at the tmux level by explicitly setting the default shell command:
tmux set-option default-command "/bin/bash"
From the tmux manual (emphasis mine):
default-command shell-command
Set the command used for new windows (if not specified
when the window is created) to shell-command, which may
be any sh(1) command. The default is an empty string,
which instructs tmux to create a **login shell** using the
value of the default-shell option.
default-shell path
Specify the default shell. This is used as the login
shell for new windows when the default-command option is
set to empty, and must be the full path of the exe‐
cutable. When started tmux tries to set a default value
from the first suitable of the SHELL environment vari‐
able, the shell returned by getpwuid(3), or /bin/sh.
This option should be configured when tmux is used as a
login shell.
As explained by Chepner in a comment below:
default-shell defaults to your preferred login shell;
default-command defaults to starting a login instance, effectively
$SHELL -l
... and in the case of Bash, a login shell doesn't read ~/.bashrc. By overriding the value of default-command, we can now force tmux to create a non-login shell instead.
This issue is not related to tmux. To solve it make sure to add source ~/.bashrc to .bash_profile and that's it.
You can learn more about bash initialization and which files it loads and in which order here: https://github.com/sstephenson/rbenv/wiki/Unix-shell-initialization#bash
As you can see .bashrc is not even on the list when bash is started in login mode, that's why we source it from the file (.bash_profile) that is on the list.

Is there a way to code Ctrl+a :multiuser on when using screen?

I want to run a script that sets up a screen session and then automatically makes it into a multi-user and also adds one of the users on my system.
So far, I have a script that creates the screen session, but I have to manually make it into a multiuser session then also add the user.
As far as I have seen there is no actual coding to do this and the only way to do it is with the Ctrl+a command.
Does anyone know of a way that means the command can be done in a bash script?
You can automatically run custom commands from a configuration file - by default $HOME/.screenrc will be loaded, if it exists, so you can just do:
echo "multiuser on" >> $HOME/.screenrc
to make your default screen start with :multiuser on. If you want to have a separate config from the default, just save the config with an alternative filename, and start screen with the -c option, e.g.
screen -c multiuser.conf
It is possible to do it without entering the screen, using -X. The following lines (run by Alice) start a script in a screen and add access for the user bob.
screen -S "myscreen" -dm bash script-that-i-like.sh
screen -S "myscreen" -X multiuser on
screen -S "myscreen" -X acladd bob
Bob can then join using:
screen -x alice/myscreen

How can I make GNU Screen start a new window at the CURRENT working directory?

By default, when you create a new window in GNU Screen, it will start in the directory where Screen is invoked. I want to start a new window in GNU Screen at the current working directory of the window I'm currently in. How can I do that?
See the GNU Screen chdir command. All new windows created in Screen use this as their initial directory. Using this, you can do something like:
chdir /home/dan/newscreendir
screen
And your new window (along with any future created windows) will be in the set directory. If it's always going to be the current working directory you may be able to set something up in your screenrc to do this one in one command.
See the GNU Screen man page. It's quite comprehensive.
Screen chdir command
Screen cannot access your shell variable nor execute backticked commands. The closest I can get to doing it in one click is with a small Bash script like this:
screen -X setenv currentdir `pwd`
screen -X eval 'chdir $currentdir' screen
Or more compactly:
screen -X eval "chdir $PWD"
screen -X sends the command to the currently running Screen session. The first line creates a variable called currentdir. The second line sends the currentdir to the chdir command and then creates a new Screen window.
The simple solution is to put the following strings in your ~/.screenrc file and then use Ctrl + X to open new windows:
bind ^x
bind ^x stuff "screen -X chdir \$PWD;screen^M"
http://www.michaelkelleher.info had more tips for intermediate/advanced screen users, but since that site seems to have gone away, you can find the archive of it in Michael Kelleher's Personal Website on Archive.org.
I didn't find any solution that would work when you already had a process running in a window, so I came up with my own idea. I added following lines to my .bash_profile file:
scr_cd()
{
cd $1
screen -X chdir $PWD
}
if [ "$TERM" == 'screen' ]; then
alias cd=scr_cd
fi
The screen's working directory is updated every time you change a directory. Someone may not like this approach, but it works like a charm.
Perhaps this is specific to Byobu, but simply typing screen opens a new window in the current directory.
To make Screen open a new tab/window in the current directory, you can add the following code to your .screenrc file:
bind c stuff "screen bash^M"
This will cause the Ctrl + a c command to open new tabs/windows in the directory of the current window/tab.
Note: You must ensure that Screen does not start a login shell by default, because that will cause the shell start in the default directory for a login shell rather than the current directory. This means that in your .screenrc file, your shell command cannot include a dash ('-') character.
For example, this is wrong (i.e., it will start a login shell):
shell -$SHELL
But this is right (i.e., it will not start a login shell):
shell $SHELL
Note 2: Unfortunately, this method does not behave exactly like the default new window/tab command in Screen. Instead, it writes the command to the current window and executes it to create the new window/tab, so it will not work during some long running shell process. In other words, this keyboard shortcut can only be executed whenever normal shell commands can be executed.
Note 3: If you want Screen to open new windows/tabs in the current directory and open a login shell, you can add the following code to your .screenrc file:
bind c stuff "screen bash -l^M"
You could also run:
screen -X eval "chdir $(pwd)"
Or if you want to start a new window as soon as you set chdir, use:
screen -X eval "chdir $(pwd)" screen
I have a nearly perfect solution for Bash. :)
If you never use password to set a lockscreen password, just add this to file $HOME/.bash_profile:
export PROMPT_COMMAND='screen -p $WINDOW -X chdir "$PWD"'
Do you need a password? With this:
# The digest of password "abc" is ID1wIq4l2t7s6
export PROMPT_COMMAND='screen -p $WINDOW -X eval "password none" "chdir \"$PWD\"" "idle 0 password ID1wIq4l2t7s6"'
I just hope the developers of Screen add the environment variable PWD as soon as possible.
In your .screenrc file, add a line that uses the chdir command if you want the same one every time.
If you have a running Screen session inside that session, you can type:
screen -X chdir [argument]
Without an argument it will be your home directory, the same result as typing cd.
If you have a script (this is a programming Q&A site) or are outside Screen and Screen is running, you can issue:
`which screen` -x -X chdir [argument]
Which you'll likely follow with running some new process in Screen with:
`which screen` -x -X screen [command to run in that directory] [arguments for the command]

Gnome-Terminal, how to start in a different directory?

Whenever I start my console gnome-terminal in Ubuntu, it starts in the home directory. How can I make it start in a different directory say ~/myfolder?
I tried to write cd ~/myfolder in ~/.profile but nothing happens.
If you start gnome-terminal like gnome-terminal --working-directory=myfolder it will start with the working directory at ~/myfolder so you could add a new entry to your menu to use that command instead of the other one.
I did this way - with script:
open 3 tabs in the same window size 170x40, each "tab" starts in a different directory.
gnome-terminal --geometry=170x40 --working-directory=myfolder1 \
--tab --working-directory=myfolder2 \
--tab --working-directory=myfolder3
Add the following to your ~/.bashrc
cd ~/myfolder
You could use the nautilus-open-terminal extension. This allows you to right-click on a folder in nautilus and open a terminal window with that directory as its working directory.
You can also run a terminal in the normal way, type "cd ", and drag a folder icon from nautilus to the window. This will paste the path of the folder into the command line and you then type return to change to that directory. You can do the same thing with regular files to paste their path and run commands on them.
Directory option
There is the option --working-directory to specify the startup directory of the terminal (no short option form).
The basic approach to open the terminal in /some/dir is
gnome-terminal --working-directory=/some/dir
but there is a trap...
Bad trap
Assuming we want to start the terminal in the directory ~/dir.
This does not work:
gnome-terminal --working-directory=~/dir
The command looks perfectly fine according to the option syntax, but the terminal starts in the home directory.
It's because it does not expand the tilde (~), for confusing reasons - see below.
Thesse do work:
gnome-terminal --working-directory=/home/auser/dir
gnome-terminal --working-directory=$HOME/dir
gnome-terminal --working-directory ~/dir
Tilde expansion
Note there is no = in the last variant. Because of this, the ~ is at the start of a shell word, and therefore is handeled by tilde expansion.
The problem is that ~ does not get expanded everywhere, but only in certain places. One of them is in variable assignments, like directory=~/dir. That's ok, ~ gets expanded to $HOME, but --working-directory=~/dir does not expand ~, because that is not a variable assignment, it only looks very similar.
Actually, this is how I turn it off for everyone by default.
gconftool-2 --direct \
--config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory/ \
--set -- type=bool /apps/nautilus-open-terminal/desktop_opens_home_dir true
From GNOME Terminal - Getting Started:
You can also specify a command that runs automatically when you start GNOME Terminal in the profile.
If the folder has a complicated path, ie not just ~/myfolder, you could create a symlink to it in your home directory so you can get to it quickly. You can also set the CDPATH environment variable to tell bash to search a list of directories when you type cd myfolder.
To open in my desired directory as root user I ran:
gnome-terminal --working-directory=/home/my-project/ -x bash -c "sudo su"
I'm impressed by
Neil's Mayhew comment
and
Volker's Siegel answer. I've tried to not only set default directory for
gnome-terminal but preserve habitual behavior of desktop environment as well (I'm using Linux Mint 17.1 Cinnamon,
GNOME Terminal 3.6.2, perhaps it also can be applied for other Gnome-congenered DEs). So let me put my two cents in.
Adding cd ~/myfolder at the very end of ~/.bashrc does the job. But as already mentioned it will affect every
interactive shell. Even more, if you open some directory in a file manager (Nemo or Nautilus or something like
this) and appeal to the context menu from there (e.g. right click and then select Open in Terminal) new instance of
gnome-terminal will be started in ~/myfolder regardless of the folder which was loaded in the file manager.
Even if you run gnome-terminal --working-directory=/some/other/folder explicitly it will still open ~/myfolder. Seems that the
approach with .bashrc is unusable.
gnome-terminal --working-directory=myfolder works fine but only when you use custom menu entry in you DE
(or custom shortcut on desktop) which runs terminal with this parameter. If you would like to run gnome-terminal from command line
or from mini-launcher (press Alt + F2), you have to type the parameter every time. Anyway this approach is more-or-less usable.
How gnome-terminal determines which folder to open? When --working-directory is not specified it opens current
working directory (e.g. $PWD) otherwise it opens directory specified explicitly.
I've found the following solution.
Create a file named gnome-terminal in your ~/bin folder. It will act as shortcut but from everywhere (start menu,
mini-launcher, other terminal instance, etc) because ~/bin is already in $PATH (at least in Linux Mint...). Make this file
executable. Then put the following content into the script:
#!/bin/bash
home_directory=~
if [ "$PWD" == "$home_directory" ]; then
# When 'gnome-terminal' was ran from either
# - start menu
# - mini-launcher
# ...
# parent directory is set to $HOME.
#
# We respect original command line arguments.
# For example, when terminal is ran from another
# terminal instance and '--working-directory' is
# specified explicitly we should left it as it is.
# If there are two '--working-directory' switches
# in the command line 'gnome-terminal' will pick up
# the last one.
#
# Also we use full path to executable here in order
# to prevent recursive calling of 'gnome-terminal' from
# '~/bin'.
/usr/bin/gnome-terminal --working-directory=/ "$#"
else
# 'gnome-terminal' was from another directory.
# We don't change anything.
/usr/bin/gnome-terminal "$#"
fi
If you run gnome-terminal from start menu you will see that current folder in new terminal is / (you can use any folder, for example, ~/myfolder because our custom wrapper is a Bash-script, so shell's expansion with work fine).
If you appeal to Open in Terminal in a file manager you will get current directory in the new terminal.
If you run gnome-terminal with explicit --working-directory parameter (perhaps, from existing terminal instance) new terminal instance will be opened in the directory you specified.

Resources