aaron.harnly.net

GNU screen hack-fu: running one command in multiple windows

I’ve long used the wonderful GNU screen text-windowing system, which allows you to do lots of neat things like detach a terminal session and reattach later, and switch between multiple terminal `windows’ within a single session.

When you have lots of gnu screen windows open, sometimes it’d be nice to run the same command on several of them — for example, cd several windows to the same directory, or ssh to the same server. I’ve always done this by copy-and-pasting, though there are some funky commands in screen for copying and pasting text between windows.

Now, thanks to the screen -X command and a short shell script, I can do this very easily.

I name the script screenex, and use it as follows:

[03:36 PM mithras@powerbook: ~] screenex 1 6 ls In windows 1 - 6, doing: ls

I simply pass the range of window numbers to run the command in, followed by the command itself. I can also omit the second number, to execute the command on just one other window:

[03:39 PM mithras@powerbook: ~] screenex 2 pine In windows 2 - 2, doing: pine

Neat! This becomes much more powerful, though, when you add substitution of the window number. When you include the token –INDEX– in the command, the window number is substituted for –INDEX–. I use this to launch ssh connections to six machines at once, which is handy when I’m running a bunch of jobs in parallel. At work we have a bunch of servers, named server1.school.edu, server2.school.edu, etc. So to connect to a different machine in each window, I just run:

[03:41 PM mithras@powerbook: ~] screenex 1 6 ssh server–INDEX–.school.edu In windows 1 - 6, doing: ssh server–INDEX–.school.edu

And I’m connected, ready to run my parallel jobs! You can also do cool stuff if you have environment variables that are indexed by number, for example WORKINGDIR1, WORKINGDIR2, etc. Anyway, I’ll save more for later.


The script:

(Note that the ^M character is a literal newline character, which you can enter in vi by typing ctrl-V, then enter.)

#!/bin/sh
#
# command to run the given command on multiple `GNU screen' windows
#  usage: screenex [begin-window] [end-window] command
# 
#  by Mithras The Prophet (mithras.the.prophet, which is a gmail account.)
# 
 
#
# returns 1 if arg is numeric, 0 otherwise
#
is_numeric()
{
	var="$1"
	if [ -z "$var" ]; then
		echo "0"
	else
		[ "$var" -eq 0 ] 2> /dev/null
		if [ $? -eq 0 -o $? -eq 1 ]; then 
			echo "1"
		else
			echo "0"
		fi
	fi
}
 
#
# if argument 1, or arguments 1 and 2 are numeric, then
#   we apply the command to just that range of windows;
#   otherwise, to all windows
#
mycommand=""
window_begin="1" # beginning of range of windows to send command to
window_end="6"  # and end
 
arg1="$1"
shift;
if [ -z "$arg1" ]; then
	exit;
fi
if [ $(is_numeric "$arg1") -eq 1 ]; then
	# this is beginning of range
	window_begin="$arg1"
 
	# try to grab a second numeric arg?
	arg2="$1"
	shift;
	if [ $(is_numeric "$arg2") -eq 1 ]; then
		# we have a second number!
		window_end="$arg2"
		# get start of command
		arg3="$1"
		shift;
		mycommand="$arg3"
	else
		# ahve second arg, but not a number
		# so it must be start of command
		window_end="$window_begin" # just do the one window
		mycommand="$arg2"
	fi
else
	# arg1 -not- numeric, 
	# so it must be start of command
	mycommand="$arg1"
fi
 
while [ ! -z "$1" ]
do
	mycommand="$mycommand \"$1\"" # rest of line
	shift
done
echo "In windows $window_begin - $window_end, doing: $mycommand"
 
#
# now execute!
#
newline=<<EOQ
 
EOQ
let "window_end = $window_end + 1" # so we can do strict -lt test
index="$window_begin"
while [ $index -lt $window_end ]
do
	thiscommand=${mycommand//--INDEX--/$index}
	screen -X at ${index}# stuff "${thiscommand}
"
	let "index = $index + 1"
done
Digg this     Create a del.icio.us Bookmark     Add to Newsvine

No Responses to “GNU screen hack-fu: running one command in multiple windows”

No comments yet

Leave a Reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word