Wake on LAN and remote shutdown
Zur Navigation springen
Zur Suche springen
Shell script /usr/bin/fwremote
#!/bin/bash
#
# Author: Frank Wulf
# Version: 1.0 (2017-10-02)
#
# This program can be used to start up or shut down a remote computer.
#
# Version history:
# 1.0 2017-10-02 Initial release
#
read_conf() {
resultvar=$1
# Read value from configuration file
val=`confget -O -f $conffile -s $rmt $1`
if [ "$val" == "" ]; then
# No value found, set to transferred value
val=$2
fi
eval $resultvar="'$val'"
}
log() {
if [ "$2" == "E" ]; then
mtype=":ERROR"
else
mtype=""
fi
echo "`date +'%Y-%m-%d %H:%M:%S'`: ${1}${mtype}"
}
start() {
sw_started=0
# Check if remote computer is online
if `ping $ipaddr -c1 1>/dev/null 2>&1`; then
# Check status from last run
if `get_status "$rmt" "Started"`; then
log "$rmt has already been started remotely."
exit 0
else
set_status "$rmt" "Online"
log "$rmt is already online and probably started manually."
exit 0
fi
else
# Remote computer is down
if [ "$macaddr" == "" ]; then
log "Error: No MAC address for $rmt defined."
exit 1
fi
# Determine active ethernet card
interface=`route|grep '^default'|grep -o '[^ ]*$'`
# Send Wake on Lan request to remote computer
etherwake -i $interface $macaddr 1>/dev/null 2>&1
if [ $? -ne 0 ]; then
log "Error: Sending Wake on Lan request failed."
exit 1
fi
log "Wake on Lan request has been sent to $rmt."
log "Waiting for startup (max. $timeout_start seconds) ..."
# Send one ping request per second to remote computer until
# a) remote computer answers or
# b) timeout is reached
start=`date +%s`
while [ $(( $(date +%s) - $timeout_start )) -lt $start ]; do
if `ping $ipaddr -c1 1>/dev/null 2>&1`; then
log "$rmt has answered to ping request."
sw_started=1
break
else
sleep 1
fi
done
if [ $sw_started -eq 1 ]; then
# Remote computer is now online, wait <delay_start> seconds
# before program will terminate
set_status "$rmt" "Started"
log "Waiting $delay_start seconds to end program ..."
sleep $delay_start
log "$rmt has been started successfully."
exit 0
else
# Remote computer did not respond within timeout range
set_status "$rmt" "Offline"
log "Timeout of $timeout_start seconds reached." "E"
exit 1
fi
fi
}
stop() {
sw_stopped=0
sw_stop_allowed=0
# Check if remote computer is online
if `ping $ipaddr -c1 1>/dev/null 2>&1`; then
log "$rmt has answered to ping request."
if [ "$cmd" == "force-stop" ]; then
# Command to force shutdown was given
sw_stop_allowed=1
else
# Check status from last run
if `get_status "$rmt" "Started"`; then
# Last run ended in "Started"
if [ "$shutdown" != "no" ]; then
sw_stop_allowed=1
fi
else
# Last run ended not in "Started", so probably a manual start
if [ "$shutdown" == "yes" ]; then
sw_stop_allowed=1
fi
fi
fi
if [ $sw_stop_allowed -eq 1 ]; then
# Call remote command to shut down
net rpc shutdown -f -t 0 -C 'System shutdown' -U $user%$pass -I $ipaddr 1>/dev/null 2>&1
if [ $? -ne 0 ]; then
log "Sending shutdown request to $rmt failed, exit code = $?." "E"
exit 1
fi
log "Shutdown request has been sent to $rmt."
log "Waiting for shutdown (max. $timeout_stop seconds) ..."
# During the shutdown send one ping request per second until
# a) remote computer does not answer anymore or
# b) timeout is reached
start=`date +%s`
while [ $(( $(date +%s) - $timeout_stop )) -lt $start ]; do
if ! `ping $ipaddr -c1 1>/dev/null 2>&1`; then
log "$rmt has stopped answering to ping request."
sw_stopped=1
break
else
sleep 1
fi
done
if [ $sw_stopped -eq 1 ]; then
# Remote computer is now offline, wait <delay_stop" seconds
# before program will terminate
set_status "$rmt" "Stopped"
log "Waiting $delay_stop seconds to end program ..."
sleep $delay_stop
log "$rmt has been stopped successfully."
exit 0
else
# Remote computer has still answered the ping requests when
# timeout has been reached
set_status "$rmt" "Online"
log "Timeout of $timeout_stop seconds reached." "E"
exit 1
fi
else
# Shutdown not allowed
if [ "$shutdown" == "no" ]; then
log "Remote shutdown not allowed due to configuration restriction."
else
set_status "$rmt" "Online"
log "Remote shutdown not allowed as $rmt seems to be started manually."
fi
exit 0
fi
else
# Remote computer is already offline
if `get_status "$rmt" "Stopped"`; then
log "$rmt is already offline and probably stopped remotely."
else
set_status "$rmt" "Offline"
log "$rmt is already offline and probably stopped manually."
fi
exit 0
fi
}
status() {
# Check status of last run
if `get_status "$rmt" "Started"`; then
sw_started=1
sw_stopped=0
else
sw_started=0
# Last run ended not in "Started", check if it ended in "Stopped"
if `get_status "$rmt" "Stopped"`; then
sw_stopped=1
else
sw_stopped=0
fi
fi
# Check if remote computer is online
if `ping $ipaddr -c1 1>/dev/null 2>&1`; then
if [ $sw_started -eq 1 ]; then
log "$rmt is online and probably started remotely."
else
log "$rmt is online and probably started manually."
fi
exit 0
else
if [ $sw_stopped -eq 1 ]; then
log "$rmt is offline and probably stopped remotely."
else
log "$rmt is offline and probably stopped manually."
fi
# Return with an error so that caller can distinguish between
# online and offline by checking the exit code
exit 1
fi
}
show() {
if [ "$ipaddr" == "" ]; then
ipaddr="<missing>"
fi
if [ "$macaddr" == "" ]; then
macaddr="<missing>"
fi
if [ "$user" == "" ]; then
user="<missing>"
fi
if [ "$pass" == "" ]; then
pass="<missing>"
else
# Password must not be shown in plain text
pass="<defined>"
fi
if [ "$shutdown" == "" ]; then
shutdown="<missing>"
fi
echo "ipaddr: $ipaddr"
echo "macaddr: $macaddr"
echo "user: $user"
echo "pass: $pass"
echo "shutdown: $shutdown"
echo "timeout_start: $timeout_start"
echo "delay_start: $delay_start"
echo "timeout_stop: $timeout_stop"
echo "delay_stop: $delay_stop"
}
get_status() {
if `grep "^$1" $statusfile|grep -q "$2$"`; then
return 0
else
return 1
fi
}
set_status() {
grep -v "^$1" $statusfile >$statusfile.tmp
mv $statusfile.tmp $statusfile
echo "$1:$2" >>$statusfile
}
# Define configuration file
conffile=/etc/fwremote.conf
# Define status file
statusfile=/var/run/fwremote.state
if [ ! -f $statusfile ]; then
# Status file does not exist, create an empty one
>$statusfile
fi
# Setup arguments
cmd=$1
rmt=$2
if [ ! "$rmt" == "" ]; then
# Read values from configuration file
read_conf "timeout_start" "0"
read_conf "timeout_stop" "0"
read_conf "delay_start" "0"
read_conf "delay_stop" "0"
read_conf "shutdown" "auto"
read_conf "ipaddr" "$rmt"
read_conf "macaddr" ""
read_conf "user" ""
read_conf "pass" ""
fi
case $cmd in
start)
start
;;
stop|force-stop)
stop
;;
status)
status
;;
show)
show
;;
*)
echo "Usage: $0 <command> <remote computer>"
echo ""
echo "Commands:"
echo ""
echo " start Wakes up remote computer"
echo " stop Shuts down remote computer"
echo " force-stop Force shutdown of remote computer"
echo " status Shows status of remote computer"
echo " show Shows configuration for remote computer"
exit 1
esac
exit 0
Configuration file /etc/fwremote.conf
# During remote start the program sends ping requests to the remote
# computer. If timeout has exceeded and remote system is still offline
# then the script will stop with a FAIL.
timeout_start=60
# During remote shutdown the program sends ping requests to the remote
# computer. If timeout has exceeded and remote system is still online
# then the script will stop with a FAIL.
timeout_stop=60
# During remote start this is a delay of n seconds between remote system
# starts answering ping requests and end of program.
delay_start=30
# During remote shutdown this is a delay of n seconds between remote system
# stops answering ping requests and end of program.
delay_stop=10
# This directive controls the shutdown behaviour
# yes: Force shutdown if shutdown is requested
# no: Ignore shutdown request
# auto: Shutdown only if system has been started remotely
shutdown=auto
[wulf-pc]
ipaddr=wulf-pc
macaddr=ac:22:0b:78:b6:59
user=<remote user>
pass=<remote password>
timeout_start=120
timeout_stop=120
delay_start=60
delay_stop=5
[cgefi0067]
ipaddr=cgefi0067
macaddr=ec:f4:bb:20:77:10
user=<remote user>
pass=<remote password>
timeout_start=120
timeout_stop=180
delay_stop=5