I am using my laptop via shell terminal to log on school’s server to run a
Matlab session. The session will take about 10 hours and I want to close my
laptop, go home, have dinner, and re-engage the shell terminal to check the
progress of my Matlab session.
From this link I know I should use nohup nohup to keep my terminal alive,
but I meet the following problem. Here is a screenshot of my shell after I start
running Matlab session:
where a = cv000_29590 is the respond from the Matlab. It should keep running
until cv999999 and take about 10 hours.
The problem is, this shell is not interactive anymore. I can’t enter anymore
commands, that is, I have no where to enter nohup commend to keep my SSH
session alive.
It's not really possible after you've already started a session. But for new sessions you can do the following:
Add the following to the top of your .bash_profile:
if [ -z "${PS1}" ] ; then
return
fi
if [ "${TERM}" != "screen" ] ; then
export HOSTNAME
exec screen -xRR
fi
function new {
u=${1:-$USER}
test ${u} = ${USER} && screen -t ${u}#${HOSTNAME} || screen -t ${u}#${HOSTNAME} su --login ${u}
}
Put the following content into .screenrc:
escape ^bb
shell -$SHELL
termcapinfo xterm ti#:te#
hardstatus lastline "%-Lw[%n%f %t]%+Lw%<"
screen -t ${USER}#${HOSTNAME}
These are mostly my own customizations of screen. The most important of which is that I set the screen escape character to CTRL-b instead of the default CTRL-a so I can still use CTRL-a in bash to go to the beginning of a line.
Use CTRL-b c to create shells in new windows (or just type new at the bash prompt to use the function). And use CTRL-b d to detach your session and leave it running. Next time you login, you'll be reattached to your session and everything will be as it was. Use CTRL-b n to cycle through the windows you've created. If you don't want to multiple windows, you don't have to, just use the ability to leave a session running and reattach later.
Related
Does anyone know any way of doing this? The help would be greatly appreciated, I've been beating my head over this one for a while now, and I can't seem to find any way to get scripts to auto-start and display in the foreground as they would if I had manually started them.
what i want to do is basically just power on the vm, let it boot, then watch the script run and echo results to the console or whatever the script would normally display if ran manually
I've been able to use Cron and systemd to run the script I would like to run at startup, but I cannot figure out any way to get these scripts to run in the screen, as they would if I had typed ./startup_script.sh
i am currently testing everything in a headless Debian 11 vm. Auto login as root is already enabled. i just need to complete this last step but i don't know how to do.
You can fire up a tmux session and send keys it to start a script like this:
tsid="session_name"
my_script="/home/script.sh"
# create new tmux session
tmux new-session -d -s ${tsid}
# launch the script in the tmux session
echo "launching script in a tmux session called ${tsid}"
tmux send-keys -t ${tsid} "${$my_script}" 'C-m'
I do something similar to start a "quad-pane" to my raspberry pi devices. I can send commands to each pane via ssh without looking at the screen I am sending commands to. I can send commands to the panes from any ssh session without actually connecting to a gui, or being in the "session". This way, another machine can have that session up on a monitoring display and I can momentarily ssh over a command to the host and it will show over there without ever actually connecting to the window. The panes can run scripts and and have the output on the each respective screen/pane waiting for me to connect later and look at it. Every now and then I'll pull up my quad feed to see what's happening... then disconnect and leave it all running.
# function to send an arbitrary command to a tmux pane
# arg1: full id of pane, e.g. "pi4-host01:quad-feed.0"
# arg2+ command(s) to send to pane
tmux_send_command_to_pane_id() {
local tpid cmd
tpid="${1:-0}"
cmd="${#}"
echo "cmd to send to pane: ${tpid}: ${cmd}"
tmux send-keys -t "${tpid}" "${cmd}" 'C-m'
}
If you pair something like this with cron or systemd, i'd imagine you could get to your goal relatively quick. It does depend on installing tmux. I know others use screen, but I have become a fan of tmux for whatever reason.
A nice answer on systemd scripts here -> https://unix.stackexchange.com/a/47715/376937
Here is another question that may help as well:
Tmux command to run shell command on active pane?
I'm lazy, and I prefer that computers do my work for me. I ssh into several machines on a daily basis, so I created a simple script that launches some xterm windows and places them in positions I want (as you can see, I'm using bash):
#!/bin/bash
xterm -geometry 80x27+1930+0 &
xterm -geometry 80x27+2753+0 &
xterm -geometry 80x27+1930+626 &
xterm -geometry 80x27+2753+626 &
However, the next thing I do is go to the first window and type in
ssh server_a
then in the second
ssh server_b
and so on. What I'd like to do is have my script do the ssh commands in each xterm window, and then leave the windows open for me to do my work. I've seen the -e option for xterm, but the window closes after I execute my command. Is there a way to do this?
I apologize if this is a duplicate question. I've searched around and haven't had any luck with this. Many thanks!
I'd love to see a more elegant answer, but what I came up with does work:
xterm -e bash -c 'echo foo; exec bash'
Replace echo foo with the command of your choice, and you're good to go.
This answer gives one of the best answers I've seen so far to do this. Use the bash --init-file flag either in the shebang or when executing the terminal:
#!/bin/bash --init-file
commands to run
... and execute it as:
xterm -e /path/to/script
# or
gnome-terminal -e /path/to/script
# or
the-terminal -e bash --init-file /path/to/script/with/no/shebang
My only real complaint with the exec option is if the command executed prior to exec bash is long running and the user interrupts it (^C), it doesn't run the shell. With the --init-file option the shell continues running.
Another option is cmdtool from the OpenWin project:
/usr/openwin/bin/cmdtool -I 'commands; here'
# or
/usr/openwin/bin/cmdtool -I 'commands; here' /bin/bash
... where cmdtool injects the commands passed with -I to the slave process as though it was typed by the user. This has the effect of leaving the executed commands in the shell history.
Another option is to use gnome terminator. This creates and positions terminals interactively, and you can set up each terminal to run commands within terminator preferences.
Also does lots of extra tricks using keybindings for things like move, rotate, maximise/minimise of terminals within the containing terminator window
See: https://superuser.com/a/610048
"ClusterSSH controls a number of xterm windows via a single graphical console window to allow commands to be interactively run on multiple servers over an ssh connection"
https://github.com/duncs/clusterssh/wiki
$ cssh server_a server_b
$ command
I'm lazy, and I prefer that computers do my work for me. I ssh into several machines on a daily basis, so I created a simple script that launches some xterm windows and places them in positions I want (as you can see, I'm using bash):
#!/bin/bash
xterm -geometry 80x27+1930+0 &
xterm -geometry 80x27+2753+0 &
xterm -geometry 80x27+1930+626 &
xterm -geometry 80x27+2753+626 &
However, the next thing I do is go to the first window and type in
ssh server_a
then in the second
ssh server_b
and so on. What I'd like to do is have my script do the ssh commands in each xterm window, and then leave the windows open for me to do my work. I've seen the -e option for xterm, but the window closes after I execute my command. Is there a way to do this?
I apologize if this is a duplicate question. I've searched around and haven't had any luck with this. Many thanks!
I'd love to see a more elegant answer, but what I came up with does work:
xterm -e bash -c 'echo foo; exec bash'
Replace echo foo with the command of your choice, and you're good to go.
This answer gives one of the best answers I've seen so far to do this. Use the bash --init-file flag either in the shebang or when executing the terminal:
#!/bin/bash --init-file
commands to run
... and execute it as:
xterm -e /path/to/script
# or
gnome-terminal -e /path/to/script
# or
the-terminal -e bash --init-file /path/to/script/with/no/shebang
My only real complaint with the exec option is if the command executed prior to exec bash is long running and the user interrupts it (^C), it doesn't run the shell. With the --init-file option the shell continues running.
Another option is cmdtool from the OpenWin project:
/usr/openwin/bin/cmdtool -I 'commands; here'
# or
/usr/openwin/bin/cmdtool -I 'commands; here' /bin/bash
... where cmdtool injects the commands passed with -I to the slave process as though it was typed by the user. This has the effect of leaving the executed commands in the shell history.
Another option is to use gnome terminator. This creates and positions terminals interactively, and you can set up each terminal to run commands within terminator preferences.
Also does lots of extra tricks using keybindings for things like move, rotate, maximise/minimise of terminals within the containing terminator window
See: https://superuser.com/a/610048
"ClusterSSH controls a number of xterm windows via a single graphical console window to allow commands to be interactively run on multiple servers over an ssh connection"
https://github.com/duncs/clusterssh/wiki
$ cssh server_a server_b
$ command
When using GNU screen, if you enter a screen session and then split it into desired layout.. is it possible to also have a full screen shell that you can switch to within the same session? Or once you start splitting does that mean you are constrained to one view and you can only alternate between visible split panes and then switch active shells within those panes?
I often split a screen session to monitor multiple logs or looped command output at the same time but I'd also like a full screen shell to work on as well without having to have a separate screen sessions that i need to detach from split/attach to full screen etc..
If screen can't do this, can tmux or similar do it? Any pointers?
many thanks
fLo
I tried to do this with screen. The best I could come up with was to have multiple sessions (with different escape characters). The multiple log windows were all in one session, and the other session contains, in one window, screen -r log. Then I could split the log session, and still be able to cycle through the other session windows.
I believe it is possible in tmux, but I have not made the switch (yet).
EDIT: It definitely is possible, and very easy, in tmux. And the switch was very easy (there's a screen-keys.conf file in tmux examples that I started with). This is a script I wrote to create a full screen session with 3 windows, the third has 3 panes in it, one 20% and the other two 40%. It's callable from crontab: #reboot
tmux new-session -d -s base /bin/bash
tmuxwin() {
tmux new-window -t base -n $1 /bin/bash
sleep 1
shift
tmux send "$1" C-m
}
tmuxwin second "echo second"
# These all end up in one window
tmuxwin thirddotone "echo 3.1"
tmuxwin thirddottwo "echo 3.2"
tmuxwin thirddotthree "echo 3.3"
# join 3.1 to 3.2. Give 3.1 20%
tmux select-window thirddotone
tmux joinp -p 80 -s +
# join 3.3 to 3.2. Even split
tmux joinp -s +
# and fix the names...
tmux rename-window three
# I am waiting for you, Vizzini. You told me to go back to the beginning.
# So I have. This is where I am, and this is where I’ll stay. I will not be moved.
tmux select-window -t 0
So my recommendation is to switch to tmux. I've been using tmux for less than a week and am not looking back.
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]