]> arthur.barton.de Git - trigger-rcmd.git/blob - scripts/trigger-rcmd
Fix shellcheck(1) warnings and make script more portable
[trigger-rcmd.git] / scripts / trigger-rcmd
1 #!/bin/sh
2 #
3 # trigger-rcmp: Trigger remote commands
4 # Copyright (c)2014-2016 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 [--no-wake|-n] <rcmd> [<rcmd> [...]]" >&2
20         exit 2
21 }
22
23 do_rcmd() {
24         SYSTEM="localhost"
25         IFACE="eth0"
26         CMD="uptime"
27         TIMEOUT="300"
28         SSH_CHECKS="6"
29         WAKE_DELAY="10s"
30         BOOT_DELAY="1m"
31         SHUTDOWN_TIME="+10"
32
33         # Read in job/configuration file, but ignore shellcheck(1) warnings:
34         # shellcheck disable=1090
35         . "$cnf"
36
37         if [ $? -ne 0 ]; then
38                 echo "$NAME: Failed to read \"$cnf\"!"
39                 return 2
40         fi
41
42         NAME="$NAME($1)"
43
44         echo "$NAME: Checking system \"$SYSTEM\" ..."
45         fping -c1 -q "$SYSTEM" 2>/dev/null
46         if [ $? -ne 0 ]; then
47                 if [ -n "$NO_WAKE" ]; then
48                         echo "$NAME: \"$SYSTEM\" seems to be down, skipping job."
49                         return 9
50                 fi
51
52                 echo "$NAME: \"$SYSTEM\" seems to be down, wake it up ..."
53                 etherwake -b -i "$IFACE" "$(echo "$SYSTEM" | cut -d'.' -f1)"
54                 if [ $? -ne 0 ]; then
55                         echo "$NAME: Failed to wake \"$SYSTEM\"!" >&2
56                         return 3
57                 fi
58                 echo "$NAME: Waiting for \"$SYSTEM\" to respond ..."
59                 for i in $(seq 1 $TIMEOUT); do
60                         fping -c1 -q "$SYSTEM" 2>/dev/null
61                         [ $? -ne 0 ] || break
62                         sleep 1s
63                 done
64                 fping -c1 -q "$SYSTEM" 2>/dev/null
65                 if [ $? -ne 0 ]; then
66                         echo "$NAME: Failed to wake \"$SYSTEM\"!" >&2
67                         return 4
68                 fi
69                 sleep "$WAKE_DELAY"
70                 rsys_was_running=0
71         else
72                 echo "$NAME: \"$SYSTEM\" is already alive, ok."
73                 rsys_was_running=1
74         fi
75
76         for i in $(seq 1 $SSH_CHECKS); do
77                 echo "$NAME: Checking SSH connection ($i/$SSH_CHECKS) ..."
78                 ssh -q "$SYSTEM" true >/dev/null 2>&1 && break
79                 echo "$NAME: SSH on \"$SYSTEM\" not ready. Waiting ..."
80                 sleep 10s
81         done
82         echo "$NAME: Ok, SSH seems to be available on \"$SYSTEM\"."
83
84         if [ "$rsys_was_running" -eq 0 ]; then
85                 echo "$NAME: \"$SYSTEM\" just started up. Delaying actions for $BOOT_DELAY ..."
86                 sleep "$BOOT_DELAY"
87         fi
88
89         echo "$NAME: Calling \"$CMD\" on \"$SYSTEM\" ..."
90         echo
91
92         # shellcheck disable=2029
93         ssh -q "$SYSTEM" "$CMD" </dev/null ; r=$?
94
95         echo
96         echo "$NAME: Remote command ended with return code $r."
97         sleep 2
98
99         if [ "$rsys_was_running" -eq 0 ]; then
100                 rsys_users=$(ssh -q "$SYSTEM" w | tail -n +3 | wc -l)
101                 if [ "$rsys_users" = "0" ]; then
102                         echo "$NAME: Power off \"$SYSTEM\" again ..."
103                         # shellcheck disable=2029
104                         ssh -q "$SYSTEM" "sync; shutdown -hP $SHUTDOWN_TIME" >/dev/null
105                         if [ $? -ne 0 ]; then
106                                 echo "$NAME: Failed to power off \"$SYSTEM\"!" >&2
107                                 return 5
108                         fi
109                 else
110                         echo "$NAME: Not shutting down \"$SYSTEM\", \c"
111                         [ "$rsys_users" -eq 1 ] \
112                                 && echo "There is 1 user logged in!" \
113                                 || echo "There are $rsys_users users logged in!"
114                 fi
115         else
116                 echo "$NAME: \"$SYSTEM\" was already alive, not shutting down."
117         fi
118         [ $r -eq 0 ] && return 0 || return 1
119 }
120
121 # Defaults
122 NO_WAKE=
123
124 # Check required tools
125 for t in fping ssh etherwake; do
126         if ! command -v "$t" >/dev/null 2>&1; then
127                 echo "$NAME: Required tool \"$t\" missing, aborting!"
128                 exit 3
129         fi
130 done
131
132 while [ $# -gt 0 ]; do
133         case "$1" in
134           --no-wake|-n)
135                 NO_WAKE=1; ;;
136           --help|-*)
137                 do_help; ;;
138           *)
139                 break
140         esac
141         shift
142 done
143
144 [ $# -gt 0 ] || do_help
145
146 result=0
147 while [ $# -gt 0 ]; do
148         cnf="$RCMD_D/$1"
149         if [ ! -r "$cnf" ]; then
150                 echo "$NAME: Can't read \"$cnf\"!"
151                 r=1
152         else
153                 echo "$NAME: Working on \"$1\" - $(date "+%Y-%m-%d %H:%M:%S")"
154                 do_rcmd "$1" ; r=$?
155                 echo "$NAME: Done ($r) - $(date "+%Y-%m-%d %H:%M:%S")"
156         fi
157         [ $r -ne 0 ] && result=1
158         shift
159         [ $# -gt 0 ] && echo
160 done
161 exit $result