I have a screen session running with several windows. I want to attach to it, create a new screen window within it and start a shell in that new window.
Question: How can I do this from the command line outside the screen session?
I already tried a lot, e. g. screen -x (but it attaches to one of the existing screen windows; it does not create a new one nor does it start a new shell). Any hints are welcome.
Environment is Linux (Ubuntu 12.04).
Add new detached window to sesion_name and run command
screen -S sesion_name -x -X screen bash -c 'command; exec bash'
To choose a window to join, use the -p option. Giving + will create a new one, so your command is simply:
screen -x session_name -p +
This is documented on the man page:
-p n̲u̲m̲b̲e̲r̲_o̲r̲_n̲a̲m̲e̲|̲-̲|̲=̲|̲+̲
Preselect a window. This is useful when you want to reattach to a
specific windor or you want to send a command via the "-X" option
to a specific window. As with screen's select commant, "-" selects
the blank window. As a special case for reattach, "=" brings up the
windowlist on the blank window.
I found something on the mailing list, thank you tuxuday :)
I'm doing it now this way:
#!/bin/bash
screen -X screen -t NEWWINDOW # create new window (switches existing attached terminal)
sleep 0.1
screen -X other # switch existing attached terminal back to its old window
sleep 0.1
gnome-terminal -e 'screen -x -p NEWWINDOW' # connect to new window
I'm not sure about those sleeps, maybe they aren't necessary in all environments, but I can wait those 0.2s easily.
My .bash_aliases is changing the screen window title with a delay, so the awkward NEWWINDOW won't stick for long (and thus not hinder further calls to this script).
Related
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.
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
I have a bash-script in which I want to display an image to the user. This is possible using ImageMagick's display.
display image.png
But now the focus of the terminal window is lost, and is placed to the image. To continue my bash-script I have to ask the user to click on the terminal before continuing. This is unwanted behaviour.
Is there a way to display an image without losing the focus of my bash terminal? I want it to get it work on Ubuntu Linux (12.04).
Here is a not-too-awkward solution using wmctrl:
wmctrl -T master$$ -r :ACTIVE: ; display image.png & sleep 0.1 ; wmctrl -a master$$
To explain, I'll break it down into steps:
wmctrl -T master$$ -r :ACTIVE:
To control a window, wmctrl needs to know its name, which by default is its window title. So, this step assigns the current window to a unique name master$$ where the shell will expand $$ to a process ID number. You may want to choose a different name.
display image.png &
This step displays your image as a "background" process. The image window will grab focus.
sleep 0.1
We need to wait enough time for display to open its window.
wmctrl -a master$$
Now, we grab focus back from display. If you chose a different name for your master window in step 1, use that name here in place of master$$.
If wmctrl is not installed on your system, you will need to install it. On debian-like systems, run:
apt-get install wmctrl
wmctrl supports Enlightenment, icewm, kwin, metacity, sawfish, and all other EWMH/NetWM compatible X-window managers.
Alternative approach that doesn't require knowing the window title
First, get the ID of the current window:
my_id=$(wmctrl -l -p | awk -v pid=$PPID '$3 == pid {print $1}')
We can now use this ID in place of a window title. To launch display while maintaining focus in the current window:
display image.png & sleep 0.1 ; wmctrl -i -a "$my_id"
in addition to John1024 answer.
yet another way to get wid of active window:
$ xdotool getwindowfocus
and set focus:
$ xdotool windowfocus <wid>
so the full command will look like this (note the option -i, it is important!):
$ wid=$(xdotool getwindowfocus); display image.png & sleep 0.1; xdotool windowfocus $wid
p.s. read about xdotool.
Without losing the focus of terminal you can use sublime text to open any image
subl image.png
You can use picterm, it was created for this purpose: https://github.com/artemsen/picterm
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]