-
Notifications
You must be signed in to change notification settings - Fork 0
/
run_server.sh
executable file
·149 lines (115 loc) · 4.08 KB
/
run_server.sh
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
#!/bin/bash
# -*- coding: utf-8, tab-width: 2 -*-
function run_cli_main () {
export LANG{,UAGE}=en_US.UTF-8 # make error messages search engine-friendly
local SELFFILE="$(readlink -m -- "$BASH_SOURCE")"
local SELFPATH="$(dirname -- "$SELFFILE")"
cd -- "$SELFPATH" || return $?
local -A CFG=(
[run_task]='run_server_show_log_on_failure'
[lint]=
[run_prog]='nodemjs'
[log_dest]="logs.@$HOSTNAME/server.log"
)
tty --silent || CFG[run_task]='actually_run_server'
log_progress "Reading config file(s) for host '$HOSTNAME'."
local ITEM=
for ITEM in cfg.@"$HOSTNAME"{/*,.*,}.rc; do
[ ! -f "$ITEM" ] || source_in_func "$ITEM" cfg:annosrv || return $?
done
"${CFG[run_task]}" "$@" || return $?
}
function log_progress () { printf '%(%F %T)T P: %s\n' -1 "$*"; }
function source_in_func () {
source -- "$@" || return $?$(
echo W: "$FUNCNAME failed (rv=$?) for '$1'" >&2)
}
function run_server_show_log_on_failure () {
( # These parens force a subprocess with separate stdout and stderr,
# so their redirection to `log_dest` won't interfere with our `less`.
actually_run_server "$@"
)
local RV="$?"
[ "$RV" == 0 ] || less -S +G -- "${CFG[log_dest]}" || return $?
return "$RV"
}
function actually_run_server () {
tee_output_to_logfile || return $?
verify_sigterm_compat || return $?
verify_run_prog || return $?
local LINT="${CFG[lint]}"
if [ -n "$LINT" ]; then
[ "$LINT" == + ] && LINT='elp'
log_progress "Running linter: $LINT"
"$LINT" || return $?
fi
# In case we're process ID 1 (e.g. in docker), we must either forward
# signals like SIGTERM, or hand over PID 1 to a program that can ensure
# proper forwarding to the server.
# The easiest solution is to always hand over our PID to the server
# itself, independent of whether our PID is 1.
log_progress "Gonna replace pid $$ with: ${CFG[run_prog]}"
exec "${CFG[run_prog]}" src/runServer.mjs "$@" || return $?$(
echo "E: server exec failed, rv=$?" >&2)
}
function tee_output_to_logfile () {
local LOG="${CFG[log_dest]}"
[ -n "$LOG" ] || return 0
mkdir --parents -- "$(dirname -- "$LOG")"
local OLD="$(dirname -- "$LOG")/"
OLD="${OLD#./}prev.$(basename -- "$LOG")"
[ ! -f "$LOG" ] || mv --verbose --no-target-directory \
-- "$LOG" "$OLD" || return $?
>"$LOG" || return 4$(echo "E: Cannot write to logfile: $LOG" >&2)
exec &> >(tee_output_to_logfile__then_optimize) || return 71
}
function tee_output_to_logfile__then_optimize () {
tee -- "$LOG" || return $?
"$SELFPATH"/src/unclutter_server_logfile.sed -i -- "$LOG" || return $?
}
function verify_sigterm_compat () {
local PID1_CMD="$(ps ho args 1)"
if <<<"$PID1_CMD" grep -qPe "(^|/)(node|nodejs|npm)\b"; then
echo "E: Process ID 1 seems to be npm." \
"This usually causes signal handling problems, mostly with SIGTERM." \
"If you're running this in a docker container, please use" \
"'$SELFFILE' as the docker command." >&2
return 80
fi
}
function verify_run_prog () {
local NMBIN="$SELFPATH"/node_modules/.bin
if [[ ":$PATH:" != *":$NMBIN:"* ]]; then
PATH="$NMBIN:$PATH:"
export PATH
fi
local PROG="${CFG[run_prog]}"
case "$PROG" in
'!no_verify!'* ) CFG[run_prog]="${PROG#!*!}"; return 0;;
esac
log_progress "Verify run_prog: $PROG"
{ which "$PROG" && </dev/null "$PROG" -e 0; } &>/dev/null && return 0
local MAYBE=(
"$SELFPATH/node_modules/.bin/$PROG"
"/usr/lib/node_modules/.bin/$PROG"
"/usr/lib/node_modules/$PROG/bin/$PROG"
)
local ALTN=
for ALTN in "${MAYBE[@]}" ''; do
if [ -z "$ALTN" ]; then
log_progress "Using npm to search for run_prog locally." \
"This may take a few seconds."
ALTN="$(npm run sh which nodemjs | grep -Pe '^/')"
fi
[ -x "$ALTN" ] || continue
log_progress "Trying probable run_prog: $ALTN"
</dev/null "$ALTN" -e 0 &>/dev/null || continue
log_progress "Adjusting run_prog to: $ALTN"
CFG[run_prog]="$ALTN"
return 0
done
echo "E: Even npm cannot find $PROG." \
"Is the package installed correctly?" >&2
return 81
}
run_cli_main "$@"; exit $?