




















@@ -131,92 +131,123 @@ set -euo pipefail
131131printf "%s %s\n" "\$(date -u +%H:%M:%S)" "\$*" >>"$SYSTEMCTL_LOG"
132132133133filtered=()
134-for arg in "\$@"; do
134+for ((i = 1; i <= \$#; i++)); do
135+ arg="\${!i}"
135136 case "\$arg" in
136- --user|--quiet|--no-page|--now) ;;
137+ --user|--quiet|--no-page|--now|--value) ;;
138+ --property)
139+ i=\$((i + 1))
140+ ;;
141+ --property=*) ;;
137142 *) filtered+=("\$arg") ;;
138143 esac
139144done
140145command="\${filtered[0]:-status}"
141146147+is_running() {
148+ [ -s "$GATEWAY_PID_FILE" ] || return 1
149+ local pid
150+ pid="\$(cat "$GATEWAY_PID_FILE" 2>/dev/null || true)"
151+ [ -n "\$pid" ] || return 1
152+ kill -0 "\$pid" >/dev/null 2>&1
153+}
154+155+stop_gateway() {
156+ [ -s "$GATEWAY_PID_FILE" ] || return 0
157+ local pid
158+ pid="\$(cat "$GATEWAY_PID_FILE" 2>/dev/null || true)"
159+ if [[ "\$pid" =~ ^[0-9]+$ ]] && [ "\$pid" -gt 1 ] && kill -0 "\$pid" >/dev/null 2>&1; then
160+ kill "\$pid" >/dev/null 2>&1 || true
161+ for _ in \$(seq 1 100); do
162+ kill -0 "\$pid" >/dev/null 2>&1 || break
163+ sleep 0.1
164+ done
165+ kill -9 "\$pid" >/dev/null 2>&1 || true
166+ fi
167+ rm -f "$GATEWAY_PID_FILE"
168+}
169+170+load_unit_environment() {
171+ local unit="\$1"
172+ while IFS= read -r line; do
173+ case "\$line" in
174+ EnvironmentFile=*)
175+ local spec="\${line#EnvironmentFile=}"
176+ for token in \$spec; do
177+ local file="\${token#-}"
178+ [ -f "\$file" ] || continue
179+ set -a
180+ # shellcheck disable=SC1090
181+ . "\$file"
182+ set +a
183+ done
184+ ;;
185+ Environment=*)
186+ local assignment="\${line#Environment=}"
187+ assignment="\${assignment#\"}"
188+ assignment="\${assignment%\"}"
189+ export "\$assignment"
190+ ;;
191+ esac
192+ done <"\$unit"
193+}
194+195+start_gateway() {
196+ local unit="$GATEWAY_UNIT_PATH"
197+ local exec_start
198+ if [ ! -f "\$unit" ]; then
199+ echo "systemctl shim: unit not found: \$unit" >&2
200+ return 1
201+ fi
202+ exec_start="\$(sed -n 's/^ExecStart=//p' "\$unit" | tail -n 1)"
203+ if [ -z "\$exec_start" ]; then
204+ echo "systemctl shim: no ExecStart in \$unit" >&2
205+ return 1
206+ fi
207+ (
208+ load_unit_environment "\$unit"
209+ export OPENCLAW_NO_RESPAWN=1
210+ echo "systemctl shim: starting: \$exec_start"
211+ nohup bash -lc "exec \$exec_start" >>"$GATEWAY_DAEMON_LOG" 2>&1 &
212+ printf '%s\n' "\$!" >"$GATEWAY_PID_FILE"
213+ )
214+}
215+142216case "\$command" in
143217 daemon-reload)
144218 echo "daemon-reload (shim: no-op)"
145219 ;;
146220 enable)
147221 echo "enable (shim: no-op)"
148222 ;;
223+ is-enabled)
224+ echo "enabled"
225+ ;;
149226 restart|start)
150- if [ -s "$GATEWAY_PID_FILE" ]; then
151- old_pid="\$(cat "$GATEWAY_PID_FILE" 2>/dev/null || true)"
152- if kill -0 "\$old_pid" 2>/dev/null; then
153- kill "\$old_pid" 2>/dev/null || true
154- sleep 0.5
155- fi
156- fi
157- unit="$GATEWAY_UNIT_PATH"
158- if [ ! -f "\$unit" ]; then
159- echo "systemctl shim: unit not found: \$unit" >&2
160- exit 1
161- fi
162- exec_start_line="\$(grep "^ExecStart=" "\$unit" | head -1 || true)"
163- exec_start="\${exec_start_line#ExecStart=}"
164- if [ -z "\$exec_start" ]; then
165- echo "systemctl shim: no ExecStart in \$unit" >&2
166- exit 1
167- fi
168- # Source EnvironmentFile if present
169- env_file_line="\$(grep "^EnvironmentFile=" "\$unit" | head -1 || true)"
170- env_file="\${env_file_line#EnvironmentFile=}"
171- env_file="\${env_file#-}"
172- if [ -n "\$env_file" ] && [ -f "\$env_file" ]; then
173- set -a; source "\$env_file"; set +a
174- fi
175- # Inline Environment= entries
176- while IFS= read -r env_line; do
177- env_entry="\${env_line#Environment=}"
178- env_entry="\${env_entry#\"}"
179- env_entry="\${env_entry%\"}"
180- export "\$env_entry"
181- done < <(grep "^Environment=" "\$unit" || true)
182- echo "systemctl shim: starting: \$exec_start"
183- eval nohup \$exec_start >>"$GATEWAY_DAEMON_LOG" 2>&1 &
184- echo "\$!" >"$GATEWAY_PID_FILE"
185- echo "systemctl shim: started pid \$(cat "$GATEWAY_PID_FILE")"
227+ stop_gateway
228+ start_gateway
186229 ;;
187230 stop)
188- if [ -s "$GATEWAY_PID_FILE" ]; then
189- pid="\$(cat "$GATEWAY_PID_FILE")"
190- kill "\$pid" 2>/dev/null || true
191- rm -f "$GATEWAY_PID_FILE"
192- fi
231+ stop_gateway
193232 ;;
194233 is-active)
195- if [ -s "$GATEWAY_PID_FILE" ] && kill -0 "\$(cat "$GATEWAY_PID_FILE" 2>/dev/null)" 2>/dev/null; then
234+ if is_running; then
196235 echo "active"
197236 else
198237 echo "inactive"
199238 exit 3
200239 fi
201240 ;;
202241 show)
203- if [ -s "$GATEWAY_PID_FILE" ] && kill -0 "\$(cat "$GATEWAY_PID_FILE" 2>/dev/null)" 2>/dev/null; then
204- pid="\$(cat "$GATEWAY_PID_FILE")"
205- echo "ActiveState=active"
206- echo "SubState=running"
207- echo "MainPID=\$pid"
208- echo "ExecMainStatus=0"
209- echo "ExecMainCode=0"
242+ if is_running; then
243+ printf 'ActiveState=active\nSubState=running\nMainPID=%s\nExecMainStatus=0\nExecMainCode=0\n' "\$(cat "$GATEWAY_PID_FILE")"
210244 else
211- echo "ActiveState=inactive"
212- echo "SubState=dead"
213- echo "MainPID=0"
214- echo "ExecMainStatus=0"
215- echo "ExecMainCode=0"
245+ printf 'ActiveState=inactive\nSubState=dead\nMainPID=0\nExecMainStatus=0\nExecMainCode=0\n'
216246 fi
217247 ;;
218248 *)
219- echo "systemctl shim: ignoring: \$*"
249+ echo "systemctl shim: unsupported command: \$*" >&2
250+ exit 1
220251 ;;
221252esac
222253SHIMEOF
@@ -226,9 +257,12 @@ echo "systemctl shim installed."
226257# Now install the gateway service using node-A.
227258echo "Installing gateway service..."
228259mkdir -p "$(dirname "$GATEWAY_UNIT_PATH")"
229-# gateway install may exit non-zero because our systemctl shim cannot fully
230-# restart, but the unit file gets written before the restart step.
231-openclaw gateway install --json >"$ARTIFACTS/gateway-install.json" 2>"$ARTIFACTS/gateway-install.err" || true
260+if ! openclaw gateway install --json >"$ARTIFACTS/gateway-install.json" 2>"$ARTIFACTS/gateway-install.err"; then
261+ echo "FAIL: gateway install failed before update"
262+ cat "$ARTIFACTS/gateway-install.json" 2>/dev/null || true
263+ cat "$ARTIFACTS/gateway-install.err" 2>/dev/null || true
264+ exit 1
265+fi
232266233267echo ""
234268echo "── Step 4: Inspect what node path was baked into the service ──"
@@ -268,6 +302,10 @@ echo "process.execPath will be: $(node -e "console.log(process.execPath)")"
268302echo ""
269303echo "── Step 6: Run openclaw update (this is the bug) ──"
270304305+UPDATE_FAILED=0
306+GATEWAY_START_FAILED=0
307+GATEWAY_HEALTH_FAILED=0
308+271309# Run the update WITH restart so that the update flow re-runs
272310# `gateway install --force` and bakes the current process.execPath
273311# (now node-B) into the service unit. This is where the split happens.
@@ -281,9 +319,12 @@ echo ""
281319echo "Update exit code: $UPDATE_EXIT"
282320echo "Update stderr (if any):"
283321cat "$ARTIFACTS/update.err" 2>/dev/null | tail -10 || true
322+if [ "$UPDATE_EXIT" -ne 0 ]; then
323+ UPDATE_FAILED=1
324+fi
284325285-# The update may fail during restart (systemctl shim limitations) but it must
286-# have at least attempted the package install. Check that it ran past early exit.
326+# Keep inspecting after a non-zero update so the log shows whether the unit was
327+# rewritten, but fail immediately if update never reached the service refresh.
287328if [ "$UPDATE_EXIT" -ne 0 ] && ! grep -q "gateway" "$ARTIFACTS/update.err" 2>/dev/null; then
288329 echo "FAIL: openclaw update failed before reaching the package install step"
289330 cat "$ARTIFACTS/update.err" 2>/dev/null || true
@@ -364,22 +405,35 @@ echo "── Step 9: Try starting the gateway with the post-update unit ──"
364405GATEWAY_START_FAILED=0
365406if [ -f "$GATEWAY_UNIT_PATH" ]; then
366407 systemctl restart 2>&1 || true
367- sleep 3
368- if [ -s "$GATEWAY_PID_FILE" ] && kill -0 "$(cat "$GATEWAY_PID_FILE" 2>/dev/null)" 2>/dev/null; then
369- echo "OK: Gateway started (pid $(cat "$GATEWAY_PID_FILE"))"
370- # Try a health probe.
371- if openclaw gateway status --json >"$ARTIFACTS/status.json" 2>&1; then
372- echo "OK: Gateway status probe succeeded"
373- else
374- echo "WARNING: Gateway status probe failed"
375- fi
376- # Stop it.
377- kill "$(cat "$GATEWAY_PID_FILE")" 2>/dev/null || true
408+ if PORT=18789 node <<NODE
409+const url = "http://127.0.0.1:" + process.env.PORT + "/healthz";
410+const deadline = Date.now() + 30000;
411+const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
412+let last = "timeout";
413+while (Date.now() < deadline) {
414+ try {
415+ const response = await fetch(url);
416+ if (response.ok) {
417+ process.exit(0);
418+ }
419+ last = "HTTP " + response.status;
420+ } catch (error) {
421+ last = error instanceof Error ? error.message : String(error);
422+ }
423+ await sleep(500);
424+}
425+console.error(last);
426+process.exit(1);
427+NODE
428+ then
429+ echo "OK: Gateway healthz probe succeeded"
378430 else
379- echo "BUG: Gateway failed to start with the post-update unit"
380- cat "$GATEWAY_DAEMON_LOG" 2>/dev/null | tail -20 || true
431+ echo "BUG: Gateway healthz probe failed with the post-update unit"
381432 GATEWAY_START_FAILED=1
433+ GATEWAY_HEALTH_FAILED=1
434+ cat "$GATEWAY_DAEMON_LOG" 2>/dev/null | tail -20 || true
382435 fi
436+ systemctl stop 2>&1 || true
383437fi
384438385439echo ""
@@ -403,9 +457,15 @@ if [ -f "$GATEWAY_UNIT_PATH" ]; then
403457 EXIT_CODE=1
404458 fi
405459fi
460+if [ "$UPDATE_FAILED" -ne 0 ]; then
461+ EXIT_CODE=1
462+fi
406463if [ "$GATEWAY_START_FAILED" -ne 0 ]; then
407464 EXIT_CODE=1
408465fi
466+if [ "$GATEWAY_HEALTH_FAILED" -ne 0 ]; then
467+ EXIT_CODE=1
468+fi
409469exit $EXIT_CODE
410470' || CONTAINER_EXIT=$?
411471此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。