-
Notifications
You must be signed in to change notification settings - Fork 0
/
manage-ghar
253 lines (216 loc) · 5.86 KB
/
manage-ghar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#!/bin/bash
set -eu
PID_FILE="runner.pid"
LOG_FILE="runner.log"
STATE_DIRNAME="state"
CONFIG_FILE=".manage_ghar.conf"
VERSION="0.1.0"
# check if runner is running based on the existence of a state file and based
# on a valid PID
is_running () {
local state_path="$1"
# if no PID file, it's not running
if [[ ! -f $state_path/$PID_FILE ]]
then
return 1
fi
local pid
pid=$(cat "$state_path/$PID_FILE")
# check PID exists
if ps -p "$pid" >/dev/null
then
return 0
else
return 1
fi
}
start () {
local runner_path="$1"
local state_path="$2"
local runner_command="$3"
local force=$4
# check if the runner path exists
if ! [[ -d "$runner_path" ]]
then
echo "Runner path not found" >&2
return 10
fi
# check if the runner is running
if ! $force && is_running "$state_path"
then
echo "The runner is already running" >&2
return 11
fi
# running as a service, see
# https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service
if [[ -z "$runner_command" ]]
then
runner_command="bin/runsvc.sh"
fi
cd "$runner_path"
# check if runner command is valid
if ! ([[ -x "$runner_command" ]] || type "$runner_command" >/dev/null 2>&1)
then
echo "Runner command $runner_command is invalid" >&2
return 12
fi
echo "Starting runner"
echo "Starting runner on $(hostname)" >>"$state_path/$LOG_FILE"
$runner_command >>"$state_path/$LOG_FILE" 2>&1 &
# create pid file
echo "Creating pid file"
echo $! >"$state_path/$PID_FILE"
}
stop () {
local state_path="$1"
# check if the runner is running
if is_running "$state_path"
then
local pid
pid=$(cat "$state_path/$PID_FILE")
echo "Stopping runner"
echo "Stopping runner on $(hostname)" >>"$state_path/$LOG_FILE"
kill -SIGTERM "$pid"
else
echo "Runner already stopped"
echo "Runner already stopped on $(hostname)" >>"$state_path/$LOG_FILE"
fi
echo "Removing PID file"
rm --force "$state_path/$PID_FILE"
}
status () {
local state_path="$1"
if is_running "$state_path"
then
echo "Runner started"
else
echo "Runner stopped"
fi
}
usage () {
cat <<EOF
Manage GitHub Actions Runner like a SysV init script
manage-ghar [-s STATE_PATH] [-r RUNNER_COMMAND] [-f] [-v] [-h] {start|stop|restart|status} RUNNER_PATH
Optional arguments:
-s STATE_PATH
Path to the state directory of the manager (where PID and log files are stored). Default to $STATE_DIRNAME in the runner directory.
-r RUNNER_COMMAND
Command to execute instead of running the runner directly. This command should not take any argument.
-f
Force start even if the runner is running (may have unpredictable effects).
-v
Show current version and return.
-h
Show this help message and return.
Subcommands:
start
Start the runner, it cannot be started twice. Runner's PID is stored in $PID_FILE and logs are outputed in $LOG_FILE, within the state directory.
stop
Stop the runner.
restart
Stop and start the runner.
status
Tell if the runner is running.
Mandatory arguments:
RUNNER_PATH
Path to a GitHub Actions Runner directory.
EOF
}
usage_extra () {
cat <<EOF
If there is a configuration file $CONFIG_FILE in the user home directory, then manage-ghar will use it to set the default value of the following optional arguments:
state_path
runner_command
force (true or false)
Arguments must be in the form "<key>=<value>". Arguments from the command line override those default values.
EOF
}
show_version () {
echo "manage-ghar v$VERSION"
}
main () {
# default arguments
local state_path=""
local runner_command=""
local force=false
# read configuration if available
if [[ -f "$HOME/$CONFIG_FILE" ]]
then
declare "$(env -i "$(cat "$HOME/$CONFIG_FILE")")"
fi
# process optional arguments
while getopts ":hvs:r:f" option
do
case $option in
"h")
usage
usage_extra
return 0
;;
"v")
show_version
return 0
;;
"s")
state_path="$OPTARG"
;;
"r")
runner_command="$OPTARG"
;;
"f")
force=true
;;
*)
echo "Unknown option $OPTARG" >&2
usage
return 1
;;
esac
done
shift $((OPTIND-1))
# process mandatory arguments
if [[ -z "${1+_}" ]] || [[ -z "${2+_}" ]]
then
echo "Missing arguments" >&2
usage
return 2
fi
local subcommand="$1"
local runner_path
runner_path="$(realpath "$2")"
# process state path
if [[ -z $state_path ]]
then
state_path="$runner_path/$STATE_DIRNAME"
else
state_path="$(realpath "$state_path")"
fi
mkdir -p "$state_path"
# process subcommand
case $subcommand in
"start")
start "$runner_path" "$state_path" "$runner_command" "$force"
return 0
;;
"stop")
stop "$state_path"
return 0
;;
"restart")
stop "$state_path"
sleep 1
start "$runner_path" "$state_path" "$runner_command" "$force"
return 0
;;
"status")
status "$state_path"
return 0
;;
*)
echo "Unknown subcommand $subcommand" >&2
usage
return 3
;;
esac
}
main "$@"