22 July 2008

Using GNU screen with gnome-terminal's custom shell command

GNU screen is a nice tool. It becomes more valuable when it's omnipresent, but until today I've been too lazy to get configured the way I want it:

  1. I want screen started within every new gnome-terminal.
  2. When a new terminal starts, I want a fresh screen window with a fresh shell.
  3. When I close a terminal window, my screen session should persist.

The first ups screen's usefulness since its capabilities are now always a keystroke away. The second mimics my new-terminal-window-is-a-new-task mentality. The third keeps me from accidentally losing work when I close a terminal window.

First, I needed to add several options to my ~/.screenrc:

# Useful settings (among many others)
autodetach on
multiuser on
startup_message off
# Startup commands for a new session
screen -t local
select local

Next, because gnome-terminal's custom command facility doesn't allow anything too fancy (e.g. multiple commands, variable expansion), I had to create a small bash script called gnome-terminal-command.sh:

#!/bin/bash -i
# First, construct a new window identifier
WIN_ID=`date +%R:%S`
# Second, start a new window in the screen session using that identifier
screen -xRR -X screen -t "${WIN_ID}"
# Third, prevent existing terminals from switching to the new session
# Thanks to nassrat for this tip
screen -xRR -X other
# Now, use screen to connect to the new window within this process
exec screen -xRR -p "${WIN_ID}"

Lastly, I told gnome-terminal to use gnome-terminal-command.sh under Edit -> Current Profile -> Title and Command . Check "Run a custom command instead of my shell" and give gnome-terminal-command.sh in the Custom command input box. Older versions of gnome-terminal (e.g. version 2.18.1) allow the script to be somewhere in your path. Newer versions (e.g. 2.22.1) seem to require a full path to the script. This is puzzling.

Testing it out...

  1. Start gnome-terminal and you get a screen session with one window called 'local'.
  2. Open a second gnome-terminal and you get a new screen window whose title is the current time.
  3. Close the second window and you see two screen windows persisting in the first gnome-terminal.
  4. Open a third gnome-terminal and you get yet another new screen window.
  5. Hit Control-D three times in the third window to end each of the screen windows. All of your gnome-terminals will simultaneously close.

During testing, it'll help if you have an informative screen status line. Should you run into serious troubles, you can undo the changes by using gconf-editor to tweak use_custom_command and custom_command under apps/gnome-terminal/profiles/Default.


Anonymous said...

Excellent, exactly what I was looking for, thanks!

Would be even better if the nautilus "Open in Terminal" right click option could still work.



Unknown said...

There should be a way to use $* within the script. Check if it is set to an executable file maybe. If it is, run it. If it isn't, then just exec screen like the script currently does.

I'm unfortunately not going to get a chance to look at it for awhile. Love to hear if you get it working.

- Rhys

Pykler said...
This comment has been removed by the author.
Pykler said...

I added one line to your script there.

screen -xRR -X other

right before the exec command. That should keep the previous window from switching its screen session.

Unknown said...

Thanks for the suggestion nassrat. I've added it to the content above.

Unknown said...

Updated the script above to include -i on the #!/bin/bash line. Seems that gnome-terminal does not run this command in an interactive shell, and environment settings like ~/.bashrc get lost along the way. Something you'd never notice unless you want ~/bin/screen which should be in your PATH because of your interactive shell settings.

Anonymous said...

For compatibility with "nautilus-open-terminal" you should add this line right after declaring WIN_ID:

screen -dxRR -X chdir "${PWD}"

Unknown said...

Hi sgtpep,

I've tried the following

#!/bin/bash -i

WIN_ID=`date +%R:%S`

screen -dxRR -X chdir "${PWD}"

screen -xRR -X screen -t "${WIN_ID}"

screen -xRR -X other

exec screen -xRR -p "${WIN_ID}"

which does mostly work with the nautilius-open-terminal package.

When I right click and open a terminal from nautilus, the new terminal opens in the appropriate directory. However, the new terminal does not take part in the screen session. Every other aspect of the script continues to work just fine. Is this what you intended? Or am I missing something?

AsherMaximum said...
This comment has been removed by the author.
AsherMaximum said...

You can add 'local ' after each '-xRR' to give the session a name, if you want to use other sessions for other things. I found that it always resumed the last session I had opened, which isn't what I wanted. My last line is now:

exec screen -xRR 'local' -p "${WIN_ID}"

and same for the other lines.

Anonymous said...

nassrat's addition is good, however I found that 3 out of 4 times the gnome terminal would come up blank. If I comment out "screen -xRR -X other" the problem goes away. There is some sort of race condition. The solution was to put this:

sleep 0.1

right after the "screen -xRR -X other"

Seems to work fine 100% of the time now.

Subscribe Subscribe to The Return of Agent Zlerich