How to attach to an existing byobu session or start a new one if there is no session when starting terminal emulator? - terminal

I'm using zsh and byobu (using the tmux backend).
In my .zshrc file I put the following:
if which byobu >/dev/null 2>&1; then
# if not inside a byobu session, and if no session is started,
# start a new session
test -z "$TMUX" && (byobu attach || byobu new-session)
fi
If I close the terminal emulator I'm using, then open another one, I re-attach to the byobu session I was using and all is fine. However, when I just start my computer, or if I exited byobu (for example by pressing Ctrl-D on the last open window), opening a new terminal results in this:
[exited]
~$
It seems to be because byobu attach actually returns something, so byobu new-session is never run, but I don't understand why byobu attach finds something if I quit byobu (in this case, $TMUX is empty).
How can I make sure that a new session of byobu is launched if there is no instance already running?
Thanks!

Related

How to create, name, and run a command in tmux automatically

I use tmux for a program I run that sometimes crashes, so I can collect errors from it. I use this method of error collection for a few different programs and would like to know if there's a programmatic way of creating multiple tmux sessions with bash, each having their own name and having a command ran in them.
I have tried doing the following:
tmux new -ds "myname" "my command"
tmux new -ds "myname2" "my command"
however, if the program or command in the tmux session finishes/closes/crashes the tmux session is automatically exited and closed, defeating the purpose of trying to get error output.
You have to make the command not exit. Ex. run the shell after the command, so the shell will wait for you:
tmux new -d -s my-session 'sh -c "my command; sh"'

tmux detach while running script

So I have a script that I would like to run on my server and not have it bother me. So I thought I would run the server in a tmux window and then detach it so I could simply attach if I ever want to look at the progress (this script will take days to run).
but when I run my script in the tmux window, I am not able to detatch while it is running. Is there something I am doing wrong? How can I detach while this still runs? I feel like I am being very oblivious to an obvious solution here.
You can detach from a tmux session while leaving the script running by:
CTRL + b, then pressing d
You can enter back into the session by running tmux attach -t <session id>

mosh: sources .bashrc twice with different PIDs

I use tmux in my build server. Recently I wrote a small .bashrc script that will automate attaching to tmux session if one exits. The script looks like follows
# Automate tmux Startup
if [ -z "$TMUX" ]; then
# we're not in a tmux session
if [ `ps -o comm= -p $PPID` == "sshd" ]; then
# even VNC can have $SSH_TTY and $SSH_CONNECTION set so we cant find out
# if we want to attach to tmux during ssh so we need to see if parent
# process is sshd see
# http://unix.stackexchange.com/questions/145780/linux-ssh-connection-is-set-even- without-sshing-to-the-server
# Only attach to tmux if its me
WHOAMI=$(whoami)
if tmux has-session -t $WHOAMI 2>/dev/null; then
tmux -2 attach-session -t $WHOAMI
else
echo "Start tmux with username as session name 'tmux new -s $WHOAMI' "
fi
fi #parent process check
else
echo "Inside tmux"
fi
The problem is whenever I ssh using mosh it just hangs inside the tmux window. I found that if I remove this script and then use mosh to just ssh and attach to tmux manually then I don't hit on this issue. This issue only happens if I place the above script in .bashrc.
My suspicion was that mosh is waiting for .bashrc to complete and waits for it indefinitely and in the mean time it also does not pass the mouse and keystroke controls over to tmux. I confirmed this by killing the tmux session from another terminal and found that mosh recovered and tried to execute my previously buffered keystrokes.
The strange thing is that how mosh managed to cross the ps -o comm= -p $PPID == "sshd" check. This is because for mosh the Process name of shell is bash and Parent process name of the shell is mosh-server and not sshd. Further investigation revealed that mosh executes .bashrc twice once as sshd and once as mosh-server. This is reproducible by putting ps -o comm= -p $PID -p $$ >> moshbash in .bashrc.My tmux attach was happening in sshd and hanging mosh forever.
A simple workaround I found was to do
mosh user#server -- tmux attach -t `whoami`
I can do a similar thing to my ssh as well to fire command from the client side and eliminate the .bashrc script altogether but I do not wish to spill over my server side automation to the client side.
Actually mosh does not seem to be wrong. It is sourcing a .bashrc file only once per PID .I think it is a bad design to have .bashrc kick of a blocking session to tmux since tmux also needs terminal we cant start off as a background process either so & also wont work.
Is there any other way around this problem ? I think if we can distingusih between a mosh client setting up a sshd and a ssh client setting up sshd that information can be used.
.bashrc always executes everytime an interactive non-login bash instantiates so use .bash_profile instead so it would only run once during login to ssh. If the script or processes of the script summons bash, it would cause repeated summoning.
See Bash Startup Files for more info and other startup files.

tmux session closes when ssh terminal closes

What I am trying to do:
I am trying to execute couple of bash commands on a remote machine using ssh and I want those commands to finish execution even after ssh-session is closed in the middle of execution.
What I have done so far :
I am using Putty to connect to ssh (one of the reasons of using putty is that one machine is windows and remote machine is mac-os and I need some way to initiate ssh through Python command). I am passing command.txt file and it contains all the commands I want to execute.
putty -ssh start-ts#ip.000.001.101 -m command.txt ( not real ip)
command.txt : looks like this :
export PATH=$PATH:/usr/local/bin
echo $PATH; sleep 1
tmux -c 'queue.sh'
sleep 100
After connecting to ssh, to make sure that my script/commands continue running on remote machine even after ssh-session is closed on another machine, I am using 'tmux'
But the Problem is :
Even after using tmux, processes called by queue.sh terminate as soon as I close ssh-session.
I have also tried
export PATH=$PATH:/usr/local/bin
echo $PATH; sleep 1
tmux
queue.sh
sleep 100
does the same thing.
What I also tried :
If I just pass following commands using ssh (in command.txt)
export PATH=$PATH:/usr/local/bin
echo $PATH; sleep 1
tmux
and then manually type queue.sh in tmux terminal, is that case I can close ssh-terminal and remote machine continues execution of processes.
Any suggestion ?
I want to be able to pass everything though script files and keeping the processes running on remote machine (mac-os) even after closing ssh-session on another machine.
Thanks
The -c option doesn't actually start a new session; it's for compatibility with other shells if you use tmux as a login shell. In order to run queue.sh in a tmux session, try starting tmux with
tmux new-session queue.sh

GNU screen: Launch command in session without changing window to it

We have an attended-upgrade script which launches apt-get update && apt-get upgrade simultaneously on all our administered systems. Ideally, we'd want to launch them all inside a screen session. When I do it like this:
File: upgrade.sh
for host in $ALLHOSTS
do
some_commands_which_take_considerable_time
screen -X screen sh -c "ssh $host \"apt-get update && apt-get upgrade\""
done
$ screen ./upgrade.sh
, it works, but as there are new windows arriving on the session, they are automatically being switched to. Instead, I'd rather have a version where the active window is fixed unless contained process quits or I switch manually using ^A n.
Bonus points if there is a possibility to preserve windows with exited processes, but keeping them separate from windows with active processes.
You can do this with tmux. For example:
# Start a session named "apt-get" and leave it running in the background.
tmux session-new -d -s apt-get
# Preserve windows with inactive processes.
tmux set-option -t apt-get set-remain-on-exit on
# Start a new window without switching to it. You can also do this from
# within a running tmux session, not just outside of it.
tmux new-window -d -t apt-get -n upgrade-$host \
"ssh $host 'apt-get update && apt-get upgrade'"
Note that you can have multiple windows with the same name, or modify the argument to the -n flag for unique names. The tmux application doesn't care.
As an example, you could name each window "upgrade," but that would make it difficult to identify your SSH sessions at a glance. Instead, this example appends the value of the host variable (populated by your for-loop) to each window name. This makes it easier to navigate, or to programmatically close windows you are no longer interested in. This is especially valuable when you have a lot of unclosed windows displaying terminated processes.
Overall, the syntax is a little cleaner and more intuitive than GNU screen's for this sort of task, but your mileage may vary.
W/r/t preserving windows after a subprocess exits, one possibility is to invoke the zombie command in your screen config file(s), which requires that you specify two keyboard characters that kill or resurrect the window, respectively. E.g.:
zombie KR
Then, K would kill a window whose subprocess has terminated, while R would attempt to relaunch the subprocess in the same window. Note that, in a zombie window, those keys are captured at the top level (i.e., do not precede them with your normal screen control character prefix sequence).
In order to prevent automatic switching to a newly created window, try altering your invocation of screen to something like the following:
screen -X eval 'screen sh -c "ssh $host \"apt-get update && apt-get upgrade\""' 'other'
Thanks to CodeGnome, I'll probably go with tmux as I believe there is no way to do it with screen (that's unfortunate, really!).
To give a better sketch of how it can be used:
#!/bin/sh
tmux new-session -d -s active
tmux new-session -d -s inactive
tmux set-option -t active set-remain-on-exit on
for host in $ALLHOSTS
do
tmux new-window -d -t active: -n upgrade-$host "
./do_upgrade_stuff.sh $host
tmux move-window -s active:upgrade-$host -t inactive:
"
done

Resources