Skip to content

Instantly share code, notes, and snippets.

@cowboy
Created June 9, 2010 02:45
Show Gist options
  • Save cowboy/430972 to your computer and use it in GitHub Desktop.
Save cowboy/430972 to your computer and use it in GitHub Desktop.
an irssi "helper" script
#!/bin/bash
function print_usage {
cat <<PRINT_USAGE
Usage: $(basename $0) [ -start | -restart | -check | -info ]
-start start ssh session (connect to remote server)
-restart force-restart ssh session
-check restart ssh session only if network settings have
changed since last check (use in launchd or cron)
-info more detailed information (version & installation)
PRINT_USAGE
}
function print_info {
cat <<PRINT_INFO
============================================================================
ssh/screen/irc auto-restart script v1.0 - 3/22/06
by "Cowboy" Ben Alman - http://rj3.net/cowboy/
============================================================================
$(print_usage)
Description:
This script creates a remote ssh/screen/irc session, which automatically
reconnects after ssh quits. This automatic reconnect occurs whenever ssh
disconnects (with an errorlevel != 0) OR when it gets killed by this script
in -restart or -check mode. If the screen process exits with errorlevel 0
(if detached, for example) this script will wait for a user-specified time
before auto-reconnecting.
Installation:
* Edit this script as needed (functions irc_command, irc_restart, etc).
* Ensure your ssh timeout is acceptable. For example, using these values
in your ssh configfile might cause ssh to exit after a 2 minutes timeout:
ServerAliveInterval 30
ServerAliveCountMax 4
* Copy net.rj3.cowboy.irc to ~/Library/LaunchAgents and edit as needed (to
point to the location of this script).
* Register the launch agent with this command:
launchctl load ~/Library/LaunchAgents/net.rj3.cowboy.irc
* Start ssh/screen/irc with:
irc -start
Notes:
If you don't like or have launchd, you can create a cron job to check irc.
The downside is that cron checks at most every minute, while launchd can
check every second, or when system settings (like airport) change.
Tested on OS X 10.4 Tiger, YMMV
If you have questions or suggestions, I can be found idling in efnet/#irssi.
PRINT_INFO
}
# Seconds between each retry attempt
retry_seconds=5
# Seconds before auto-reconnecting a "clean" disconnect (for example, if
# you detached the screen session from another terminal). Set to 0 to auto-
# reconnect instantly. Set to -1 to disable auto-reconnect.
retry_seconds_clean=3600
# Seconds of "good connection" after which the "reconnect attempt #N"
# counter resets. Purely for aesthetic purposes :)
countup_reset_time=60
function irc_command {
# put your ssh/screen/irc command line here
ssh -F ~/.ssh/config_irc -q -t [email protected] screen -rAadU IRC
}
function irc_restart {
# edit between the quotes on the next line. what goes in there is a
# grep pattern "guaranteed" to find your irc in the output of ps -ww
PID=$(get_pid "ssh.*IRC")
if [ "$PID" ]; then
# note: if $PID contains multiple PIDs, this kills all of them
kill $PID
fi
}
function irc_check {
if [[ $(has_network_changed) == "YES" ]]; then
irc_restart
fi
}
# temp file where current network info gets stored (required to keep
# irc -check from constantly restarting.
network_current_file=/tmp/irc_network_current
function irc_start {
REPLY=
while [[ true ]]
do
time_start=$(date "+%s")
irc_command
errorlevel=$?
time_elapsed=$(($(date "+%s") - $time_start))
if [[ $errorlevel == 0 ]]; then
if [[ $retry_seconds_clean == -1 ]]; then
display_echo "Press any key to reconnect..."
read -n 1 -r -s
display_delete
else
countdown=$retry_seconds_clean
while [[ $countdown > 0 ]]
do
display_echo "Press any key to reconnect, or wait $(print_time $countdown)..."
read -n 1 -t 1 -r -s
display_delete
if [[ $REPLY ]]; then
countdown=0
REPLY=
else
countdown=$(($countdown - 1))
fi
done
fi
countup=0
else
if [[ $time_elapsed > $countup_reset_time ]]; then
countup=0
display 1 "Disconnected!"
else
display 1 "Connect attempt failed!"
fi
countup=$((${countup:=1} + 1))
countdown=$retry_seconds
while [[ $countdown > 0 ]]
do
display 1 "Reconnect attempt #$countup in $(print_time $countdown)..."
countdown=$(($countdown - 1))
done
fi
done
}
# get the PID of a process
function get_pid {
echo $(ps -ww | grep -v get_pid | grep -v grep | grep "$@" | awk '{print $1}')
}
# get all your ips (OS X)
function get_ip {
echo $(ifconfig -u | grep -w "inet" | cut -d " " -f 2 | sed 's/^ *//;s/ *$//')
}
# get your airport's MAC address (OS X)
function get_bssid {
echo $(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | grep 'BSSID' | sed 's/.*: //')
}
# check to see if your ip(s) and/or airport connection have changed
function has_network_changed {
#network_current_file=/tmp/irc_network_current
network_current="$(get_bssid) $(get_ip)"
network_previous="$(cat $network_current_file 2> /dev/null)"
if [[ "$network_current" == "$network_previous" ]]; then
echo "NO"
else
echo "$network_current" > $network_current_file
echo "YES"
fi
}
# print some text so that it can be deleted
function display_echo {
display_text="$*"
echo -en "$display_text"
}
# delete that text
function display_delete {
for ((i=1;i<=${#display_text};i++)); do echo -en "\b \b"; done
}
# print text, wait, delete text
function display {
display_echo "$2"
sleep $1
display_delete
}
# print days/hours/minutes/seconds instead of just seconds
function print_time {
print_time_d=$(echo "scale=0;$1 / 86400" | bc -l)
print_time_h=$(echo "scale=0;($1 / 3600) - ($print_time_d * 24)" | bc -l)
print_time_m=$(echo "scale=0;($1 / 60) - ($print_time_d * 1440) - ($print_time_h * 60)" | bc -l)
print_time_s=$(echo "scale=0;$1 % 60" | bc -l)
print_time_fmt=" ${print_time_d:-0} day ${print_time_h:-0} hour ${print_time_m:-0} min ${print_time_s:-0} sec"
echo "$print_time_fmt" | sed -E "s/ 0 [^ ]*//g;s/^ //"
}
case "$1" in
-start) irc_start; exit 0;;
-check) irc_check; exit 0;;
-restart) irc_restart; exit 0;;
-info) print_info; exit 0;;
esac
print_usage
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>net.rj3.cowboy.irc</string>
<key>ProgramArguments</key>
<array>
<string>/Users/cowboy/bin/irc</string>
<string>-check</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
</array>
<key>StartInterval</key>
<integer>5</integer>
</dict>
</plist>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment