]> arthur.barton.de Git - trigger-rcmd.git/blob - scripts/trigger-rcmd
Only use publickey authentification
[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 [publickey] ($i/$SSH_CHECKS) ..."
78                 if ssh -o PreferredAuthentications=publickey -q "$SYSTEM" true >/dev/null 2>&1; then
79                         echo "$NAME: Ok, SSH seems to be available on \"$SYSTEM\"."
80                         break
81                 fi
82                 echo "$NAME: SSH on \"$SYSTEM\" not ready. Waiting ..."
83                 sleep 10s
84         done
85
86         if [ "$rsys_was_running" -eq 0 ]; then
87                 echo "$NAME: \"$SYSTEM\" just started up. Delaying actions for $BOOT_DELAY ..."
88                 sleep "$BOOT_DELAY"
89         fi
90
91         echo "$NAME: Calling \"$CMD\" on \"$SYSTEM\" ..."
92         echo
93
94         # shellcheck disable=2029
95         ssh -o PreferredAuthentications=publickey -q "$SYSTEM" "$CMD" </dev/null ; r=$?
96
97         echo
98         echo "$NAME: Remote command ended with return code $r."
99         sleep 2
100
101         if [ "$rsys_was_running" -eq 0 ]; then
102                 rsys_users=$(ssh -q "$SYSTEM" w | tail -n +3 | wc -l)
103                 if [ "$rsys_users" = "0" ]; then
104                         echo "$NAME: Power off \"$SYSTEM\" again ..."
105                         # shellcheck disable=2029
106                         ssh -o PreferredAuthentications=publickey -q "$SYSTEM" "sync; shutdown -hP $SHUTDOWN_TIME" >/dev/null
107                         if [ $? -ne 0 ]; then
108                                 echo "$NAME: Failed to power off \"$SYSTEM\"!" >&2
109                                 return 5
110                         fi
111                 else
112                         echo "$NAME: Not shutting down \"$SYSTEM\", \c"
113                         [ "$rsys_users" -eq 1 ] \
114                                 && echo "There is 1 user logged in!" \
115                                 || echo "There are $rsys_users users logged in!"
116                 fi
117         else
118                 echo "$NAME: \"$SYSTEM\" was already alive, not shutting down."
119         fi
120         [ $r -eq 0 ] && return 0 || return 1
121 }
122
123 # Defaults
124 NO_WAKE=
125
126 # Check required tools
127 for t in fping ssh etherwake; do
128         if ! command -v "$t" >/dev/null 2>&1; then
129                 echo "$NAME: Required tool \"$t\" missing, aborting!"
130                 exit 3
131         fi
132 done
133
134 while [ $# -gt 0 ]; do
135         case "$1" in
136           --no-wake|-n)
137                 NO_WAKE=1; ;;
138           --help|-*)
139                 do_help; ;;
140           *)
141                 break
142         esac
143         shift
144 done
145
146 [ $# -gt 0 ] || do_help
147
148 result=0
149 while [ $# -gt 0 ]; do
150         cnf="$RCMD_D/$1"
151         if [ ! -r "$cnf" ]; then
152                 echo "$NAME: Can't read \"$cnf\"!"
153                 r=1
154         else
155                 echo "$NAME: Working on \"$1\" - $(date "+%Y-%m-%d %H:%M:%S")"
156                 do_rcmd "$1" ; r=$?
157                 echo "$NAME: Done ($r) - $(date "+%Y-%m-%d %H:%M:%S")"
158         fi
159         [ $r -ne 0 ] && result=1
160         shift
161         [ $# -gt 0 ] && echo
162 done
163 exit $result