bash script - how to execute command after starting new tmux session - bash

For example: start new tmux session, launch webserver (sends log into console), and launch second tmux window for editor.
I had trying do this by different ways - but nothing works.

Take a look at tmuxify (disclaimer: I wrote it).
It's to automate the launch of tmux sessions by defining a layout file with windows, panes and commands.

For commands executions, take a look at this answer.
But you can also predefining layouts of tmux sessions, try tmuxinator/tmuxinator
.

You can run shell commands from ~/.tmux.conf:
if-shell shell-command export I_AM_USING_TMUX=1
But it often does not seem to work as expected...
The environment variable TMUX is set when you run tmux. Then you can conditionally run shell commands from ~/.bash_profile:
if [[ ! -z "$TMUX" ]]; then
# run shell commands
fi
Or, you can export your own environment variable from ~/.tmux.conf file (as I already exported one from the beginning) and use it for if condition from ~/.bash_profile again:
if [[ ! -z "$GHCHOI_IS_USING_TMUX" ]]; then
# run shell commands
fi

Related

bash interact just once

I want to write a script for Ubuntu, which open a terminal-emulator, which only allows users interact with it only once. After finish running user's first command typed in, the terminal close on itself automatically, which is kind of like Win+R on windows OS.
How should I do that?
I try script like gnome-terminal -- bash -c "read cmd && $cmd", but there's two problem:
No auto-complete on user inputting commands;
Commands from .bashrc, .bash_aliases are not recognized.
You can try :
gnome-terminal -- bash --rcfile <(cat ~/.bashrc; echo 'PROMPT_COMMAND="PROMPT_COMMAND=exit"')
I don't have Ubuntu to test at the moment, but bash ... part worked.

Display welcome message in new tmux session

In a bash script, a new tmux session is started, several processes are launched in separate panes, then the session is attached to the current terminal. I would like to display a short message that gives a few helpful hints how to navigate panes, exit the session etc.
I tried to just echo, but that is not executed inside the session. Is there a good approach how to do this?
Edit: my use case is to have everything contained in a repository. I want to avoid adding config to dotfiles or anything in the user's home dir.
There are a few ways you could print your message perhaps:
Make tmux enter copy mode with some output, for example: tmux new \; run 'echo hello'
Run a script in a new window that prints the output: tmux neww 'echo hello; sleep 5'
Make one of your panes (if your tmux is new enough) open a popup: tmux new 'tmux popup -KER "echo hello; sleep 5"; exec $SHELL"
You can check to see if there are tmux specific environment variables set in your .bashrc and print a message if they exist
eg. in your .bashrc
if [ ! -z "$TMUX" ]; then
echo "Your message"
fi

How to launch tmux –automatically– when konsole/yakuake start?

I discovered tmux possibility recently and I'm using it inside yakuake/konsole (quake-like terminal). However, I have to launch tmux manually every time I start my laptop or restart yakuake.
How to launch tmux –automatically– when yakuake/konsole start ?
A friend advice to use <terminal_emulator> -e tmux.
Konsole
It works with konsole.
I modified the property in the menu to:
konsole -e tmux
Yakuake
However it doesn't work with yakuake.
Based on the Start tmux on every shell login article from the Archlinux wiki, you can start tmux on your shell with the following code at the
Zsh or Bash
Add in your zsh or bash configuration (usually ~/.zshrc or ~/.bashrc) the following code and restart your session:
function start_tmux() {
if type tmux &> /dev/null; then
#if not inside a tmux session, and if no session is started, start a new session
if [[ $HOST == "laptop" && -z "$TMUX" && -z $TERMINAL_CONTEXT ]]; then
(tmux -2 attach || tmux -2 new-session)
fi
fi
}
start_tmux
Fish
Add in your fish configuration (usually ~/.config/fish/config.fish) the following code and restart your session:
function start_tmux
if type tmux > /dev/null
#if not inside a tmux session, and if no session is started, start a new session
if test -z "$TMUX" ; and test -z $TERMINAL_CONTEXT
tmux -2 attach; or tmux -2 new-session
end
end
end
start_tmux
I solved this by creating a Konsole/Yakuake profile (they're one and the same) + made it the default, in which I set up the Command to:
/usr/bin/sh -ilc "tmux attach || tmux new"
Manage profiles + where the profile is located, in case Yakuake/Konsole doesn't start up anymore:
When yakuake is running:
qdbus org.kde.yakuake /yakuake/sessions runCommandInTerminal 0 "tmux"
I haven't tried with Yakuake but I have a one liner shell scripting approach to make it work with Konsole Terminal Emulator.
Konsole emulator set KONSOLE_<something> environment variable on start.
Knowing this fact, we can add this to .zshrc file
[ -z "$KONSOLE_VERSION" ] || tmux
And this will start all KONSOLE windows attached to active tmux session or create one if its the first window.

my interactive bash script loop is breaking even if I have a trap INT that should prevent it?

on this simple script
#!/bin/bash -i
trap 'echo "(ctrl+c was hit)"' INT
while true; do
echo -n "hit Enter..";read
echo "still on loop"
done
if I hit ctrl+c it will exit the loop
if I make it not interactive with 1st line like #!/bin/bash, it will work!
the problem is I have several scripts (run with "startup applications" stored at ~/.config/autostart) that only work properly with interactivity enabled #!/bin/bash -i, mainly because they load the .bashrc again granted by -i option.
any tips?
EDIT: I found this on the begging of my ~/.bashrc file:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
that prevents loading that file as source in non interactive script, I didnt put it there and I dont know why it is there...
EDIT: so, as the problem is loading what is setup at ~/.bashrc, but to the script doesnt behave weirdly, I found that scripts started by "startup applications" stored at ~/.config/autostart, may be run this way:
xterm -e "bash -i -c myScript.sh"
#or
bash -i -c 'xterm -e "myScript.sh"' #this way the title looks better
so the script wont have -i option, will begin just with #!/bin/bash to behave properly, and the ~/.bashrc file will setup the environment properly also.
Having bash run interactively enables job control, history expansion, aliases and several other things that you probably don't want in a script, including changes to signal behavior.
If all you want is to load variables from ~/.bashrc, have you considered to just source ~/.bashrc?
From the bash man page:
When bash is interactive, in the absence of any traps, it ignores
SIGTERM (so that kill 0 does not kill an interactive shell), and **SIGINT**
is caught and handled (so that the wait builtin is interruptible).
Crt-c typically sends SIGINT (the tty driver is the one that controls what crt-c does). Consequently, bash will trap SIGNT after your trap is called in interactive mode. You could try mapping crt-c within that script to some other signal and then trap that signal (maybe SIGTERM?).

source .bashrc from .cshrc

Is it possible to source a .bshrc file from .cshrc in a non-interactive session?
I'm asking because tcsh is our default shell at work and the .cshrc has to be used to set up the environment initially.
However, I am not really familiar with the tcsh and I have my own set-up in bash, so right now I have the following lines at the end of my .cshrc file:
if ( $?prompt && -x /bin/bash) then
exec /bin/bash
endif
This works fine, loading my environment from .bashrc and giving me a bash prompt for interactive sessions but now I also need the same set-up for non-interactive sessions, e.g. to run a command remotely via SSH with all the correct PATHs etc.
I can't use 'exec' in that case but I can't figure out how to switch to bash and load the bash config files "non-interactively".
All our machines share the same home directory, so any changes to my local *rc files will affect the remote machiens as well.
Any ideas welcome - thank you for your help!
After some more research I'm now quite sure that this won't work, but of course feel free to prove me wrong!
To load the environment in bash I have to switch to a bash shell. Even if that is possible "in the background", i.e. without getting a prompt, it would still break any tcsh commands which would then be attempted to execute under bash.
Hmmmm, back to the drawing board...
If $command is set there are arguments to csh, so it is a remote shell command. This works for me in .cshrc:
if ($?command) then
echo Executing non-interactive command in bash: $command $*
exec /bin/bash -c "${command} $*"
endif
echo Interactive bash shell
exec bash -l
Test:
$ ssh remotehost set | grep BASH
BASH=/bin/bash
...
proves that it ran in Bash.

Resources