Recently I’ve been debugging code on a remote system and ended up opening several ssh connections to it from my screen session. This is suboptimal because each connection in screen just gets labeled with the name of the remote system in my setup. Running a screen session on the system itself would provide me with labels that are more informative (generally: what is running in each shell).
I have resisted running nested screens for a long time, mainly due to the additional complexity of teaching myself two separate command characters for screen, and when to use each one. For example, when copying between inner screen sessions one must use the outer command character. Some display bugs and flow control hickups also show up in the inner screen sessions.
Yesterday I ran across a tmux configuration for nested sessions and started looking into implementing something similar in screen. Migrating to tmux is another thing I’ve been resisting…
Implementing “switching” between nested screen sessions takes advantage of the following screen commands:
bindkey
for programming the sequences produced by shifted arrow keys.register
andprocess
for executing multiple screen commands from a single key press.bind
for making the necessary individual commands available from key presses.escape
for setting and resetting the command character.hardstatus
for indicating which screen is “active” (i.e. receives the “normal” command character).
To switch to the inner screen press Shift + Up Arrow and the following happens:
- The outer screen will have its status line color switched to red (
C-z V R
). - The outer screen will have its command character switched to Control G (
C-z V C-g
). - The inner screen will have its status line color switched to green (
C-z V G
).
To switch back to the outer screen press Shift + Down Arrow and the reverse happens:
- The inner screen will have its status line color switched to red (
C-z V R
). - The outer screen will have its command character switched to Control Z (
C-g V C-z
). - The outer screen will have its status line color switched to green (
C-z V G
).
Here is the relevant configuration:
# Set command character to C-z, and "C-z z" sends out a C-z character. escape ^Zz hardstatus on hardstatus alwayslastline hardstatus string "%{.g.} %2n %t%= %H " bind V command -c nested bind -c nested G hardstatus string "%{.g.} %2n %t%= %H " bind -c nested R hardstatus string "%{.R.} %2n %t%= %H " bind -c nested ^G escape ^Gg bind -c nested ^Z escape ^Zz # Shift Up --> Inner bindkey ^[[1;2A process I register I ^ZVR^ZV^G^ZVG # Shift Down --> Outer bindkey ^[[1;2B process O register O ^ZVR^GV^Z^ZVG # Use C-g V V to return to outer screen without commanding the inner one bind -c nested V process V register V ^GV^Z^ZVG
Notes:
- The same configuration is used for both the outer and inner screens.
- I’m using
C-z
as my normal command character — you may want something else.
Shortcomings:
- Detaching from the inner screen is slightly messy:
- You are left with
C-g
as the control character of the outer screen. - Pressing Shift + Down Arrow results in
C-g V R
sent to current screen. - This can be avoided by using
C-g V V
instead.
- You are left with
- Initially the status bar color of the inner screen is “wrong” (green).
- The situation becomes normal by pressing Shift + Up Arrow.
- Three copies of the
hardstatus string
setting have to be maintained.- Some additional use of
register
andprocess
could be used to avoid this.
- Some additional use of