Start tmux with cmus opend through bash script - bash

I want to open a new tmux session and window with cmus in it or, if alredy running, attach to it. At Ubuntuusers I found this Script that should do it.
1. #!/bin/bash
2. SESSION=main
3. tmux="tmux -2 -f tmux.conf"
4.
5. # if the session is already running, just attach to it.
5. $tmux has-session -t $SESSION
7. if [ $? -eq 0 ]; then
8. echo "Session $SESSION already exists. Attaching."
9. sleep 1
10. $tmux attach -t $SESSION
11. exit 0;
12. fi
I alredy know that i can do manually it with
tmux new -n music cmus
But when I use it in the script I only get the Message
usage: new-session [-d] [-n window-name] [-s session-name] [-t target-session] [-x width] [-y height] [command]
I also tried it with new-session, but no change. I have absolutly no clue whats the problem with the command or the script or both

The way I solved this is to have a main tmux session, that programs like mutt or cmus can either start or connect to. For example, for cmus I have an alias:
alias cmus='monkeys -n music cmus'
With monkeys being the following script:
#! /bin/sh
name=monkeys
# make sure tmux server is running:
tmux start-server
# determine if monkeys session is running:
tmux has-session -t ${name}
# no monkeys running, create monkeys,
# if more than one argument, take it as a command to run
# on monkeys, else just attach to monkeys
if [ "$?" != "0" ]; then
tmux new-session -s ${name} $*
elif [ $# -gt 0 ]; then
tmux new-window -t ${name} $*
else
tmux a -t ${name}
fi

Related

How to create a Tmux and Xpanes session into one splited window

I'm running a bash script that creates an Xpanes and Tmux sessions based on list of hosts (SSH to each host in the list with some extra arguments).
The issue now is that every xpanes command is created in a different window instead of one window with split panes.
If I'm running the same command separately (not via the script) it is work as excepted.
What am i missing here? or how can i attached all those windows to one splitted window?
Here is my code:
#!/bin/bash
#validate if TMUX session is running
if ! [ -n "$TMUX" ]; then
echo "This must be run from a Tmux session, please create a Tmux session first"
exit 0
fi
set +x
for srv in `cat hostsList.txt`; do \
echo "[$srv]"
RAND=`echo $srv | md5sum | awk '{print $1}'`
cp ~/.ssh/id_rsa{,_$RAND}
cp ~/.ssh/id_rsa{.pub,_$RAND.pub}
xpanes -c "{}" "<my SSH command>" ;
rm ~/.ssh/id_rsa_$RAND ~/.ssh/id_rsa_${RAND}.pub &
done

How to completely close terminal (Ubuntu bash) from TMUX session?

Can someone please help as how can I close the bash terminal completely from inside of TMUX session (closing TMUX session as well)?
Below code is from my .bashrc where TMUX session starts as soon as terminal launches
if command -v tmux &> /dev/null && [ -z "$TMUX" ]; then tmux attach -t default -c "$HOME" || tmux new -s default -c "$HOME" fi
Thanks!
You can use tmux detach -P to both detach and send HUP to the parent process, which should make it exit as well.

"Right Click > Open In Terminal" Does not work if I activate tmux whenever I start a new shell session

I am using Linux Mint 20 Ulyana, Cinnamon 4.6.6
I am using the following code to activate tmux whenever I start a new shell session.
function tmux-as-default-terminal () {
if command -v tmux &> /dev/null && [ -n "$PS1" ] && [[ ! "$TERM" =~ screen ]] && [[ ! "$TERM" =~ tmux ]] && [ -z "$TMUX" ]; then
tmux attach -t default || tmux new -s default
fi
}
tmux-as-default-terminal
However, It has a small issue. When I right click a directory and click "Open In Terminal", it does not open that path. Instead it just open the previous tmux session.
What could be done here?
Update 1
I figured out tmux new-session -c $PWD open a new tmux session in current directory.
tmux attach -t 0 -c $PWD \; new-window \; attach to existing session and open a new window with current directory.
This bit of information might be important to solve this puzzle.
Update 2
From Is it possible to send input to a tmux session without connecting to it? I found out that I can use
$ tmux new -d -s mySession
$ tmux send-keys -t mySession.0 "^U"
$ tmux send-keys -t mySession.0 "cd /tmp" ENTER
$ tmux a -t mySession
to cd to a directory in current session.
Update 3
A solution with some strings attached
function tmux-as-default-terminal () {
if command -v tmux &> /dev/null && [ -n "$PS1" ] && [[ ! "$TERM" =~ screen ]] && [[ ! "$TERM" =~ tmux ]] && [ -z "$TMUX" ]
then
if tmux has-session -t default
then
tmux send-keys -t default.0 "^U"
tmux send-keys -t default.0 "cd $PWD &> /dev/null" ENTER
tmux send-keys -t default.0 "^L"
tmux attach-session -t default.0
else
tmux new-session -s default -c $PWD
fi
fi
}
tmux-as-default-terminal
It works, as long as I do not open multiple terminals simultaneously.
OP here. for each tmux client, it will create a new session.
function tmux-as-default-terminal () {
if command -v tmux &> /dev/null && [[ ! "$TERM" =~ screen ]]
then
notmuxsession=$(tmux list-clients | wc -l)
# notmuxsession=$(ps -e | grep "tmux: client" | wc -l)
# notmuxsession=$(tmux ls | cut -d: -f1 | grep "default.*" | wc -l)
if tmux has-session -t default${notmuxsession}
then
# tmux send-keys -t default${notmuxsession}:!.! "^U"
tmux send-keys -t default${notmuxsession}:1.1 "^U"
tmux send-keys -t default${notmuxsession}:1.1 "cd $PWD &> /dev/null" ENTER
tmux send-keys -t default${notmuxsession}:1.1 "^L"
tmux attach-session -t default${notmuxsession}:1.1
else
tmux new-session -s default${notmuxsession} -c $PWD
fi
fi
}
tmux-as-default-terminal
Which tmux session you will be attached to by default, depends on how many clients are open.

Run command in new background tmux window and wait for process to finish

I'm trying to use tmux in a script, so that it runs a command that takes some time (let's say 'ping -c 5 8.8.8.8', for example) in a new hidden pane, while blocking the current script itself until the ping ends.
By "hidden pane", I mean running the command in a new pane that would be sent in background, and is still accessible by switching panes in order to monitor and/or interact with it (not necessarily ping).
(cf. EDIT)
Here is some pseudo bash code to show more clearly what I'm trying to do:
echo "Waiting for ping to finish..."
echo "Ctrl-b + p to switch pane and see running process"
tmux new-window -d 'ping -c 5 8.8.8.8' # run command in new "background" window
tmux wait-for # display "Done!" only when ping command has finished
echo "Done!"
I know the tmux commands here don't really have any sense like this, but this is just to illustrate.
I've looked at different solutions in order to either send a command in background, or wait until a process has finished in an other pane, but I still haven't found a way to do both correctly.
EDIT
Thanks to Nicholas Marriott for pointing out the -d option exists when creating a new window to avoid switching to it automatically. Now the only issue is to block the main script until the command ends.
I tried the following, hoping it would work, but it doesn't either (the script doesn't resume).
tmux new-window -d 'ping -c 5 8.8.8.8; tmux wait -S ping' &
tmux wait $!
Maybe there is a way by playing with processes (using fg,bg...), but I still haven't figured it out.
Similar questions:
[1] Make tmux block until programs complete
[2] Bash - executing blocking scripts in tmux
[3] How do you hide a tmux pane
[4] how to wait for first command to finish?
You can use wait-for but you need to give it a channel and signal that channel when your process is done, something like:
tmux neww -d 'ping blah; tmux wait -S ping'
tmux wait ping
echo done
If you think you might run the script several times in parallel, I suggest making a channel name using mktemp or similar (and removing the file when wait-for returns).
wait-for can't automatically wait for stuff like pane or windows exiting, silence in a pane, and so on, but I would like to see that implemented at some point.
The other answers are only working if you're already within a tmux session.
But if you are outside of it you've to use something like this:
tmux new-session -d 'vi /etc/passwd' \; split-window -d 'vi /etc/group' \; attach
If you want to call this within a script you should check whether or not "$TMUX" is set. (Or just unset to force a nested tmux window).
#!/bin/sh
export com1="vi /etc/passwd"
export com2="vi /etc/group"
if [ -z $TMUX ]
then
export doNewSession="new-session -d 'exit 0'"
else
export doNewSession=""
fi
tmux $doNewSession \; split-window -d $com1 \; split-window -d $com2 \; attach;
[ -z $TMUX ] && exit 0
My solution was to make a named pipe and then wait for input using read:
#!/bin/sh
rm -f /wait
mkfifo /wait
tmux new-window -d '/bin/sh -c "ping -c 5 8.8.8.8; echo . > /wait"'
read -t 10 WAIT <>/wait
[ -z "$WAIT" ] &&
echo 'The operation failed to complete within 10 seconds.' ||
echo 'Operation completed successfully.'
I like this approach because you can set a timeout and, if you wanted, you could extend this further with other tmux controls to kill the ongoing process if it doesn't end the way you want.

How to detect if tmux is attached to a session in bash?

I have a .sh file which create a new session for tmux and add some windows, the file should be used only when no session exist. For instance:
tmux new-session -A -s `ax` -n ui -d
# add windows and other magic here...
I want prevent creating a session with the same name and recreating the windows in case the .sh file is accidentally re executed and the session is running.
Basically what I need is:
If a tmux session ax does not exist with that session name, create that session. If
I am not attached to a tmux session, attach to that session.
I would like to know how to detect if a tmux session exist and if tmux is attached to it, in this example ax is running and preventing the execution of the .sh script or if the session does not exit I want to re-execute the .sh script.
Currently I was thinking to use:
tmux ls | grep attached
I would like to know if you know a better way.
It's a little hard to understand what you mean. I'm interpreting it as
if a tmux session does not exist with that session name, create it. If I am not attached to a tmux session, attach to that session name.
If this is wrong, please comment.
I have similar functionality in my scripts. All I do is
tmuxstart() {
tmux ls | grep "sess" && { tmux a -t sess; return 0; }
#rest of tmux script to create session named "sess"
tmux a -t sess
}
If the session named "sess" exists, then I execute the next 2 grouped commands on the line (attach to it and exit the function).
Note that I do not have to check if I'm already attached to the function. tmux does this automatically. If you try to attach to a tmux session while in a session, it will respond
sessions should be nested with care, unset $TMUX to force
and not recursively attach. Tmux is smart enough to keep us from shooting ourselves in the foot.
You can use $TMUX to detect if already attached, my code is:
if [ ! "$TMUX" ]; then
tmux attach -t main || tmux new -s main
fi
I use this in my ~/.bashrc so if no sessions exist, start them & detach from all but ipfs session.
IPFS_SESSION=$(tmux attach-session -t ipfs 2>&1)
if [ "$IPFS_SESSION" == "sessions should be nested *" ]; then
unset TMUX
else
if ! tmux has-session -t sql; then tmux new-session -d -s sql; fi
if ! tmux has-session -t tmp; then tmux new-session -d -s tmp; fi
if ! tmux has-session -t ytdl; then tmux new-session -d -s ytdl; fi
if ! tmux has-session -t ipfs; then tmux new-session -s ipfs; fi
fi

Resources