Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/sbin/openrc-run
- # Copyright 2011 Chad Joan
- # Distributed under the terms of the Boost License
- depend() {
- need sshd
- use net dns logger NetworkManager
- after dns sshd
- }
- _print_ssh_command() {
- eerror " ssh -L $monitor_port:127.0.0.1:$monitor_port -R $monitor_port:127.0.0.1:$monitor_port2 -N -p $connect_port -R $listen_port:localhost:22 \"$bastion_username@$bastion_hostname\""
- }
- # Returns "0" if things are fine, "1" if autossh/ssh crashed somehow.
- # If there are problems, then this will attempt to stop the daemon, kill any
- # related processes, and remove the pidfile.
- # If things are fine, this will declare AUTOSSH_PID and SSH_PID.
- _validate() {
- success="0"
- # Make sure autossh is still running.
- AUTOSSH_PID=$(cat $PID_PATH)
- AUTOSSH_PID_TEST=$(ps -o pid= --pid $AUTOSSH_PID)
- if [ -z "$AUTOSSH_PID_TEST" ]; then
- eerror "Could not find process for recorded autossh pid $AUTOSSH_PID"
- eerror "This means it crashed for some reason."
- eerror "This is probably something autossh specific, rather than a problem"
- eerror "with ssh connectivity. For example, choosing the same monitor port"
- eerror "for two different autossh services can cause one service to block"
- eerror "the local listening port that the other need, thus causing autossh"
- eerror "to exit with an error status."
- eerror "If you want to test the ssh connectivity itself, here is an "
- eerror "estimation of the command used by autossh:"
- _print_ssh_command
- success=1
- fi
- # Make sure the child process (ssh itself, as spawned by autossh)
- # exists.
- AUTOSSH_PID=$(cat $PID_PATH)
- if [ "$success" == "0" -a -n "$AUTOSSH_PID" ]; then
- SSH_PID=$(ps -o pid= --ppid $AUTOSSH_PID)
- if [ -z "$SSH_PID" ]; then
- if [ "$verbosity" == "loud" ]; then
- eerror "Did not detect child PID for autossh instance with PID $AUTOSSH_PID."
- eerror "This likely indicates a connection failure."
- eerror "If you want to find out why, try running the following command manually:"
- _print_ssh_command
- eerror "The autossh instance will now be stopped."
- fi
- success=1
- # If autossh is still running, kill it.
- AUTOSSH_PID_TEST=$(ps -o pid= --pid $AUTOSSH_PID)
- if [ -n "$AUTOSSH_PID_TEST" ]; then
- start-stop-daemon --stop --quiet \
- --pidfile $PID_PATH \
- --signal 9 \
- --exec $EPREFIX/usr/bin/autossh
- kill $AUTOSSH_PID
- fi
- # Delete the pidfile.
- if [ -f "$PID_PATH" ]; then
- rm $PID_PATH
- fi
- fi
- fi
- return $success
- }
- _require_config_var() {
- var_name=$1
- eval var_contents=\$$var_name
- if [ -z "$var_contents" ] ; then
- eend "Required setting '${var_name}_$CONFIG_SUFFIX' not defined in /etc/conf.d/autossh; aborting."
- exit 1
- fi
- }
- _get_config() {
- # Removes the text before (and including) the first dot in the current
- # service's filename, and assigns the result to the CONFIG_SUFFIX variable.
- # Thus, if /etc/init.d/autossh.foo (presumably symlinked to this script)
- # is started/stopped/whatever, then CONFIG_SUFFIX will equal "foo".
- CONFIG_SUFFIX=${RC_SVCNAME#*.}
- # The contents of the /etc/init.d/autossh file will define various
- # variables that define how we are supposed to interact with the machine
- # we are tunneling from. These "eval" statements will pick out the
- # definitions that are relevant to the current named service, and assign
- # them some easier-to-use variable names (global to this script).
- # For example, the above /etc/init.d/autossh.foo service would pick out
- # variables like host_foo, monitor_port_foo, and listen_port_foo, then
- # assign the contained values to host, monitor_port, and list_port,
- # respectively.
- eval local_username=\$local_username_$CONFIG_SUFFIX
- eval bastion_hostname=\$bastion_hostname_$CONFIG_SUFFIX
- eval bastion_username=\$bastion_username_$CONFIG_SUFFIX
- eval monitor_port=\$monitor_port_$CONFIG_SUFFIX
- eval listen_port=\$listen_port_$CONFIG_SUFFIX
- eval connect_port=\$connect_port_$CONFIG_SUFFIX
- eval verbosity=\$verbosity_$CONFIG_SUFFIX
- _require_config_var "bastion_hostname"
- _require_config_var "bastion_username"
- _require_config_var "monitor_port"
- _require_config_var "listen_port"
- if [ -z "$local_username" ]; then
- # TODO: Get current user?
- local_username="root"
- fi
- if [ -z "$connect_port" ]; then
- connect_port="22"
- fi
- if [ -z "$verbosity" ]; then
- # Be noisy by default. Folks can quiet the service after any
- # (very likely) troubleshooting is finished.
- verbosity="loud"
- fi
- # TODO: Configurability of monitor_port2 parameter.
- monitor_port2=$(($monitor_port+1))
- # Now for some simpler stuff. These make it easier to keep track of
- # our pidfile and logfile.
- PID_PATH="$EPREFIX/var/run/$RC_SVCNAME.pid"
- LOG_PATH="$EPREFIX/var/log/$RC_SVCNAME.log"
- }
- start() {
- _get_config
- if [ "$verbosity" == "loud" ]; then
- ebegin "Starting $RC_SVCNAME"
- fi
- #einfo "local_username == $local_username"
- #einfo "bastion_username == $bastion_username"
- #einfo "bastion_hostname == $bastion_hostname"
- #einfo "monitor_port == $monitor_port"
- #einfo "listen_port == $listen_port"
- #einfo "connect_port == $connect_port"
- #einfo "PID_PATH == $PID_PATH"
- # AUTOSSH_PIDFILE="$PID_PATH" \
- env \
- AUTOSSH_GATETIME=2 \
- AUTOSSH_FIRST_POLL=10 \
- AUTOSSH_POLL=60 \
- AUTOSSH_LOGLEVEL=3 \
- AUTOSSH_DEBUG=1 \
- start-stop-daemon --start --quiet \
- --background \
- --make-pidfile --pidfile $PID_PATH \
- --stdout $LOG_PATH --stderr $LOG_PATH \
- --exec $EPREFIX/usr/bin/autossh \
- --user $local_username \
- -- -M$monitor_port -N -p $connect_port -R $listen_port:localhost:22 "$bastion_username@$bastion_hostname"
- success=$?
- # Check to make sure things worked.
- if [ "$success" == "0" -a -f "$PID_PATH" ]; then
- ## If the ssh tunnel fails, it won't happen right away.
- ## We scan for a successful connection every 100ms and then give up
- ## after (approximately) 2 seconds.
- ## If it really did succeed, then the code afterwards will double check
- ## it and then agree.
- ## If it didn't succeed, then we'll have to wait a couple seconds
- ## and then the later checks will notice missing PIDs or processes
- ## then fail the service.
- #for i in `seq 1 20`;
- #do
- # #ssh -q 127.0.0.1:$monitor_port2 exit
- # netcat -z 127.0.0.1 $monitor_port2
- # if [ $? ]; then
- # break
- # fi
- # #connected=`netstat -ntl | grep -Pi "tcp\d*\s+\d+\s+\d+\s+127\.0\.0\.1:$monitor_port2\s+0\.0\.0\.0:\*\s+LISTEN"`
- # #einfo "connected = '$connected'"
- # #if [ $i -gt 2 ]; then
- # #if [ -n "$connected" ]; then break; fi
- # #fi
- # sleep 0.1
- #done
- # So far all of the above failed to provide an accurate-and-fast
- # positive confirmation. Time is precious, so I'm going to give up
- # for now and use a shitty constant delay. 0.2 seems to work well.
- sleep 0.2
- _validate
- fi
- if [ "$success" != "0" -a "$verbosity" == "loud" ]; then
- eend "Failed to start $RC_SVCNAME"
- fi
- return $success
- }
- stop() {
- _get_config
- if [ "$verbosity" == "$loud" ]; then
- ebegin "Stopping $RC_SVCNAME"
- fi
- #einfo "bastion_hostname == $bastion_hostname"
- #einfo "monitor_port == $monitor_port"
- #einfo "listen_port == $listen_port"
- _validate
- success=$?
- # In this function we will use the following convention for the $success
- # variable:
- # 0 = Success
- # 1 = Failed to stop autossh
- # 2 = autossh already crashed
- if [ "$success" == "1" ]; then success="2"; fi
- # If it isn't already messed up, try to stop it.
- if [ "$success" == "0" ]; then
- # Use the start-stop-daemon to attempt to stop autossh and clean
- # up any other state that this script might miss.
- if [ -f "$PID_PATH" ]; then
- start-stop-daemon --stop --quiet \
- --pidfile $PID_PATH \
- --exec $EPREFIX/usr/bin/autossh
- #--signal 9 \
- if [ "$?" != 0 ]; then success="1"; fi
- else
- ewarn "$PID_PATH does not exist. There may be a stray autossh instance running."
- success="1"
- fi
- # Just incase the autossh process doesn't go down peacefully, we can
- # use the SSH_PID variable defined by _validate to kill the ssh
- # process. (First make sure the ssh process is still running.)
- # Typically this will convince autossh to close itself.
- SSH_PID=$(ps -o pid= --pid $SSH_PID)
- if [ -n "$SSH_PID" ]; then
- kill $SSH_PID
- if [ "$?" != "0" ]; then success=1; fi
- fi
- # One last chance: we'll look for proof-positive this time.
- AUTOSSH_PID=$(ps -o pid= --pid $AUTOSSH_PID)
- if [ -z "$AUTOSSH_PID" ]; then success=0; fi
- fi
- if [ "$success" == "2" ]; then
- ewarn "$RC_SVCNAME: autossh was already stopped or crashed."
- success=0
- fi
- if [ "$success" != "0" -a "$verbosity" == "loud" ]; then
- eend "Failed to stop $RC_SVCNAME"
- fi
- return $success
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement