c21a21f55103bdca0484092b81660181445f4fb0
[trigger-rcmd.git] / scripts / trigger-rcmd
1 #!/bin/sh
2 #
3 # trigger-rcmp: Trigger remote commands
4 # Copyright (c)2014 Alexander Barton (alex@barton.de)
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 # Please read the file COPYING, README and AUTHORS for more information.
11 #
12
13 NAME="`basename "$0"`"
14 RCMD_D="/usr/local/etc/rcmd.d"
15
16 PATH="$PATH:/usr/local/sbin:/usr/sbin"
17
18 do_help() {
19         echo "Usage: $0 <rcmd> [<rcmd> [...]]" >&2
20         exit 2
21 }
22
23 do_rcmd() {
24         SYSTEM="localhost"
25         IFACE="eth0"
26         CMD="uptime"
27         TIMEOUT="180"
28         SSH_CHECKS="6"
29
30         . "$cnf"
31
32         if [ $? -ne 0 ]; then
33                 echo "$NAME: failed to read \"$cnf\"!"
34                 return 2
35         fi
36
37         NAME="$NAME($1)"
38
39         echo "$NAME: checking system \"$SYSTEM\" ..."
40         fping -c1 -q "$SYSTEM" 2>/dev/null
41         if [ $? -ne 0 ]; then
42                 if [ -n "$NO_WAKE" ]; then
43                         echo "$NAME: \"$SYSTEM\" seems to be down, skipping job."
44                         return 9
45                 fi
46
47                 echo "$NAME: \"$SYSTEM\" seems to be down, wake it up ..."
48                 etherwake -b -i "$IFACE" `echo "$SYSTEM" | cut -d'.' -f1`
49                 if [ $? -ne 0 ]; then
50                         echo "$NAME: failed to wake \"$SYSTEM\"!" >&2
51                         return 3
52                 fi
53                 echo "$NAME: waiting for \"$SYSTEM\" to respond ..."
54                 for i in `seq 1 $TIMEOUT`; do
55                         fping -c1 -q "$SYSTEM" 2>/dev/null
56                         [ $? -ne 0 ] || break
57                         sleep 1s
58                 done
59                 fping -c1 -q "$SYSTEM" 2>/dev/null
60                 if [ $? -ne 0 ]; then
61                         echo "$NAME: failed to wake \"$SYSTEM\"!" >&2
62                         return 4
63                 fi
64                 sleep 3
65                 rsys_was_running=0
66         else
67                 echo "$NAME: \"$SYSTEM\" is already alive, ok."
68                 rsys_was_running=1
69         fi
70
71         for i in `seq 1 $SSH_CHECKS`; do
72                 echo "$NAME: checking SSH connection ($i/$SSH_CHECKS) ..."
73                 ssh -q "$SYSTEM" true >/dev/null 2>&1 && break
74                 echo "$NAME: SSH on \"$SYSTEM\" not ready. Waiting ..."
75                 sleep 10s
76         done
77
78         echo "$NAME: calling \"$CMD\" on \"$SYSTEM\" ..."
79         echo
80
81         ssh -q "$SYSTEM" "$CMD" </dev/null ; r=$?
82
83         echo
84         echo "$NAME: remote command ended with return code $r."
85         sleep 2
86
87         if [ "$rsys_was_running" -eq 0 ]; then
88                 rsys_users=`ssh -q "$SYSTEM" w | tail -n +3 | wc -l`
89                 if [ "$rsys_users" = "0" ]; then
90                         echo "$NAME: power off \"$SYSTEM\" again ..."
91                         ssh -q "$SYSTEM" "sync; shutdown -hP +1"
92                         if [ $? -ne 0 ]; then
93                                 echo "$NAME: failed to power off \"$SYSTEM\"!" >&2
94                                 return 5
95                         fi
96                 else
97                         echo "$NAME: not shutting down \"$SYSTEM\", \c"
98                         [ $rsys_users -eq 1 ] \
99                                 && echo "there is 1 user logged in!" \
100                                 || echo "there are $rsys_users users logged in!"
101                 fi
102         else
103                 echo "$NAME: \"$SYSTEM\" was already alive, not shutting down."
104         fi
105         [ $r -eq 0 ] && return 0 || return 1
106 }
107
108 # Defaults
109 NO_WAKE=
110
111 while [ $# -gt 0 ]; do
112         case "$1" in
113           --no-wake|-n)
114                 NO_WAKE=1; ;;
115           --help|-*)
116                 do_help; ;;
117           *)
118                 break
119         esac
120         shift
121 done
122
123 [ $# -gt 0 ] || do_help
124
125 result=0
126 while [ $# -gt 0 ]; do
127         cnf="$RCMD_D/$1"
128         if [ ! -r "$cnf" ]; then
129                 echo "$NAME: can't read \"$cnf\"!"
130                 r=1
131         else
132                 echo "$NAME: working on \"$1\" - `date "+%Y-%m-%d %H:%M:%S"`"
133                 do_rcmd "$1" ; r=$?
134                 echo "$NAME: done ($r) - `date "+%Y-%m-%d %H:%M:%S"`"
135         fi
136         [ $r -ne 0 ] && result=1
137         shift
138         [ $# -gt 0 ] && echo
139 done
140 exit $result