nterminal 1.2.16 → 1.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/bin/nterminal.js +1 -0
- package/dist/client/assets/{MarkdownPreview-EXPZkKVj.js → MarkdownPreview-BfwhfniS.js} +1 -1
- package/dist/client/assets/{index-2oIP_yU8.js → index-8FTmdvif.js} +10 -10
- package/dist/client/index.html +1 -1
- package/dist/server/update/packageUpdate.js +2 -2
- package/dist/server/update/packageUpdate.js.map +1 -1
- package/dist/shared/manualUpdate.d.ts +1 -1
- package/dist/shared/manualUpdate.js +2 -2
- package/dist/shared/manualUpdate.js.map +1 -1
- package/docs/configuration.md +1 -0
- package/docs/onboarding.md +1 -1
- package/docs/operations.md +2 -2
- package/package.json +1 -1
- package/scripts/nterminalctl +263 -57
package/dist/client/index.html
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="64x64" href="/icons/favicon-64.png" />
|
|
13
13
|
<link rel="icon" type="image/png" sizes="96x96" href="/icons/favicon-96.png" />
|
|
14
14
|
<title>NTerminal</title>
|
|
15
|
-
<script type="module" crossorigin src="/assets/index-
|
|
15
|
+
<script type="module" crossorigin src="/assets/index-8FTmdvif.js"></script>
|
|
16
16
|
<link rel="stylesheet" crossorigin href="/assets/index-B3-WG4Tf.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
@@ -101,7 +101,7 @@ export function getVersionInfo(cwd = appDir(), manualUpdate = null) {
|
|
|
101
101
|
export function checkPackageUpdate(cwd = appDir()) {
|
|
102
102
|
const currentVersion = runningPackageVersion(cwd);
|
|
103
103
|
const packageName = readPackageName(cwd);
|
|
104
|
-
const latest = npm(['view', `${packageName}@latest`, 'version'], cwd);
|
|
104
|
+
const latest = npm(['view', `${packageName}@latest`, 'version', '--prefer-online'], cwd);
|
|
105
105
|
if (!latest.ok) {
|
|
106
106
|
return {
|
|
107
107
|
currentVersion,
|
|
@@ -134,7 +134,7 @@ export function runUpdate(cwd = appDir()) {
|
|
|
134
134
|
const packageName = readPackageName(cwd);
|
|
135
135
|
const installedVersion = readPackageVersion(cwd);
|
|
136
136
|
if (!check.latestVersion || installedVersion !== check.latestVersion) {
|
|
137
|
-
const install = npm(['install', '-g', `${packageName}@latest
|
|
137
|
+
const install = npm(['install', '-g', `${packageName}@latest`, '--prefer-online'], cwd, packageUpdateTimeoutMs);
|
|
138
138
|
if (!install.ok) {
|
|
139
139
|
releaseUpdateLock(cwd);
|
|
140
140
|
const output = install.stderr || install.stdout || 'npm install -g failed';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageUpdate.js","sourceRoot":"","sources":["../../../src/server/update/packageUpdate.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"packageUpdate.js","sourceRoot":"","sources":["../../../src/server/update/packageUpdate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ManualUpdateInfo } from './protocol.js';
|
|
2
|
-
export declare const manualUpdateMessage = "Automatic update needs write access to the global npm install. Run the manual update command
|
|
2
|
+
export declare const manualUpdateMessage = "Automatic update needs write access to the global npm install. Run the manual update command as the NTerminal runtime user; only the npm install step should use sudo.";
|
|
3
3
|
export declare function createManualUpdateInfo(packageName?: string, detectedAt?: Date): ManualUpdateInfo;
|
|
4
4
|
export declare function isPermissionUpdateFailure(output: string): boolean;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export const manualUpdateMessage = 'Automatic update needs write access to the global npm install. Run the manual update command
|
|
1
|
+
export const manualUpdateMessage = 'Automatic update needs write access to the global npm install. Run the manual update command as the NTerminal runtime user; only the npm install step should use sudo.';
|
|
2
2
|
export function createManualUpdateInfo(packageName = 'nterminal', detectedAt = new Date()) {
|
|
3
3
|
return {
|
|
4
4
|
reason: 'permission',
|
|
5
5
|
message: manualUpdateMessage,
|
|
6
|
-
command: `sudo npm i -g ${packageName}@latest && nterminal restart`,
|
|
6
|
+
command: `sudo npm i -g ${packageName}@latest --prefer-online && nterminal restart`,
|
|
7
7
|
detectedAt: detectedAt.toISOString()
|
|
8
8
|
};
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manualUpdate.js","sourceRoot":"","sources":["../../src/shared/manualUpdate.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAC9B,
|
|
1
|
+
{"version":3,"file":"manualUpdate.js","sourceRoot":"","sources":["../../src/shared/manualUpdate.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAC9B,wKAAwK,CAAC;AAE3K,MAAM,UAAU,sBAAsB,CAAC,WAAW,GAAG,WAAW,EAAE,UAAU,GAAG,IAAI,IAAI,EAAE;IACvF,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,mBAAmB;QAC5B,OAAO,EAAE,iBAAiB,WAAW,8CAA8C;QACnF,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,OAAO,qKAAqK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5L,CAAC"}
|
package/docs/configuration.md
CHANGED
|
@@ -38,6 +38,7 @@ Onboarding writes `.env` for you, including an absolute `NTERMINAL_STATE_PATH` s
|
|
|
38
38
|
| `NTERMINAL_FILE_TEXT_MAX_BYTES` | `1048576` | Maximum bytes loaded for text or Markdown view/edit. |
|
|
39
39
|
| `NTERMINAL_FILE_PREVIEW_MAX_BYTES` | `52428800` | Maximum bytes served for browser file previews. |
|
|
40
40
|
| `NTERMINAL_PID_PATH` | `~/.nterminal/nterminal.pid` | PID file for the control script. |
|
|
41
|
+
| `NTERMINAL_MONITOR_PID_PATH` | `~/.nterminal/nterminal.monitor.pid` | PID file for the lightweight restart supervisor. |
|
|
41
42
|
| `NTERMINAL_LOG_PATH` | `~/.nterminal/nterminal.log` | Log file for the control script. |
|
|
42
43
|
| `NTERMINAL_HEALTH_TIMEOUT_SECONDS` | `15` | Startup health-check timeout for the control script. |
|
|
43
44
|
| `NTERMINAL_STOP_TIMEOUT_SECONDS` | `20` | Graceful stop timeout for the control script. |
|
package/docs/onboarding.md
CHANGED
|
@@ -7,7 +7,7 @@ npm install -g nterminal
|
|
|
7
7
|
nterminal onboarding
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
NTerminal stores `.env`, state, pid, and log files under `~/.nterminal`. Install with a user-writable npm global prefix so in-app updates can run `npm install -g nterminal@latest` without sudo.
|
|
10
|
+
NTerminal stores `.env`, state, pid, and log files under `~/.nterminal`. Install with a user-writable npm global prefix so in-app updates can run `npm install -g nterminal@latest --prefer-online` without sudo.
|
|
11
11
|
|
|
12
12
|
## Main Server
|
|
13
13
|
|
package/docs/operations.md
CHANGED
|
@@ -13,7 +13,7 @@ nterminal restart
|
|
|
13
13
|
nterminal stop
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
The script starts
|
|
16
|
+
The script starts a lightweight supervisor in the background. The supervisor runs the built server, writes PID files, appends logs, waits for the local health endpoint, and restarts the Node process if it exits unexpectedly. `nterminal stop` stops both the supervisor and the real Node PID so PTY cleanup can run.
|
|
17
17
|
|
|
18
18
|
Runtime files are kept under `~/.nterminal`.
|
|
19
19
|
|
|
@@ -34,7 +34,7 @@ Each server updates itself as an npm package install.
|
|
|
34
34
|
The **updates** panel in the main server sidebar footer can manage the fleet:
|
|
35
35
|
|
|
36
36
|
- **Check for updates** checks the npm registry.
|
|
37
|
-
- **Update** runs `npm install -g nterminal@latest` plus restart.
|
|
37
|
+
- **Update** runs `npm install -g nterminal@latest --prefer-online` plus restart.
|
|
38
38
|
- **Update all** updates secondary servers in parallel first and the main server last.
|
|
39
39
|
|
|
40
40
|
Notes:
|
package/package.json
CHANGED
package/scripts/nterminalctl
CHANGED
|
@@ -68,6 +68,7 @@ load_env_file
|
|
|
68
68
|
|
|
69
69
|
DEFAULT_STATE_PATH="$DEFAULT_RUNTIME_DIR/state.json"
|
|
70
70
|
DEFAULT_PID_PATH="$DEFAULT_RUNTIME_DIR/nterminal.pid"
|
|
71
|
+
DEFAULT_MONITOR_PID_PATH="$DEFAULT_RUNTIME_DIR/nterminal.monitor.pid"
|
|
71
72
|
DEFAULT_LOG_PATH="$DEFAULT_RUNTIME_DIR/nterminal.log"
|
|
72
73
|
|
|
73
74
|
HOST="${NTERMINAL_HOST:-127.0.0.1}"
|
|
@@ -75,6 +76,7 @@ PORT="${NTERMINAL_PORT:-3107}"
|
|
|
75
76
|
NODE_BIN="${NTERMINAL_NODE_BIN:-node}"
|
|
76
77
|
NPM_BIN="${NTERMINAL_NPM_BIN:-npm}"
|
|
77
78
|
PID_PATH="$(resolve_path "${NTERMINAL_PID_PATH:-${NTERMINAL_RUNTIME_PID_PATH:-$DEFAULT_PID_PATH}}")"
|
|
79
|
+
MONITOR_PID_PATH="$(resolve_path "${NTERMINAL_MONITOR_PID_PATH:-${NTERMINAL_RUNTIME_MONITOR_PID_PATH:-$DEFAULT_MONITOR_PID_PATH}}")"
|
|
78
80
|
LOG_PATH="$(resolve_path "${NTERMINAL_LOG_PATH:-${NTERMINAL_RUNTIME_LOG_PATH:-$DEFAULT_LOG_PATH}}")"
|
|
79
81
|
STATE_PATH="$(resolve_path "${NTERMINAL_STATE_PATH:-${NTERMINAL_RUNTIME_STATE_PATH:-$DEFAULT_STATE_PATH}}")"
|
|
80
82
|
HEALTH_TIMEOUT_SECONDS="${NTERMINAL_HEALTH_TIMEOUT_SECONDS:-15}"
|
|
@@ -100,6 +102,7 @@ export NTERMINAL_APP_DIR="$APP_DIR"
|
|
|
100
102
|
export NTERMINAL_ENV_FILE="$ENV_FILE"
|
|
101
103
|
export NTERMINAL_STATE_PATH="$STATE_PATH"
|
|
102
104
|
export NTERMINAL_PID_PATH="$PID_PATH"
|
|
105
|
+
export NTERMINAL_MONITOR_PID_PATH="$MONITOR_PID_PATH"
|
|
103
106
|
export NTERMINAL_LOG_PATH="$LOG_PATH"
|
|
104
107
|
|
|
105
108
|
health_url() {
|
|
@@ -130,7 +133,7 @@ ensure_runtime() {
|
|
|
130
133
|
}
|
|
131
134
|
|
|
132
135
|
ensure_directories() {
|
|
133
|
-
mkdir -p "$(dirname "$PID_PATH")" "$(dirname "$LOG_PATH")"
|
|
136
|
+
mkdir -p "$(dirname "$PID_PATH")" "$(dirname "$MONITOR_PID_PATH")" "$(dirname "$LOG_PATH")"
|
|
134
137
|
: >> "$LOG_PATH"
|
|
135
138
|
chmod 600 "$LOG_PATH" 2>/dev/null || true
|
|
136
139
|
}
|
|
@@ -147,11 +150,24 @@ validate_required_env() {
|
|
|
147
150
|
return "$missing"
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
prepare_start() {
|
|
154
|
+
ensure_app_dir
|
|
155
|
+
ensure_env_file
|
|
156
|
+
ensure_runtime
|
|
157
|
+
validate_required_env || die "generate real secrets before starting"
|
|
158
|
+
ensure_directories
|
|
159
|
+
}
|
|
160
|
+
|
|
150
161
|
read_pid() {
|
|
151
162
|
[[ -f "$PID_PATH" ]] || return 1
|
|
152
163
|
read_pid_file "$PID_PATH"
|
|
153
164
|
}
|
|
154
165
|
|
|
166
|
+
read_monitor_pid() {
|
|
167
|
+
[[ -f "$MONITOR_PID_PATH" ]] || return 1
|
|
168
|
+
read_pid_file "$MONITOR_PID_PATH"
|
|
169
|
+
}
|
|
170
|
+
|
|
155
171
|
read_pid_file() {
|
|
156
172
|
local pid_path="$1"
|
|
157
173
|
[[ -f "$pid_path" ]] || return 1
|
|
@@ -166,6 +182,19 @@ is_running() {
|
|
|
166
182
|
kill -0 "$pid" 2>/dev/null
|
|
167
183
|
}
|
|
168
184
|
|
|
185
|
+
parent_pid() {
|
|
186
|
+
local pid="$1"
|
|
187
|
+
if [[ -r "/proc/$pid/status" ]]; then
|
|
188
|
+
awk '/^PPid:/ { print $2; exit }' "/proc/$pid/status" 2>/dev/null
|
|
189
|
+
return
|
|
190
|
+
fi
|
|
191
|
+
if command -v ps >/dev/null 2>&1; then
|
|
192
|
+
ps -o ppid= -p "$pid" 2>/dev/null | tr -d '[:space:]'
|
|
193
|
+
return
|
|
194
|
+
fi
|
|
195
|
+
return 1
|
|
196
|
+
}
|
|
197
|
+
|
|
169
198
|
pid_controls_app() {
|
|
170
199
|
local pid="$1"
|
|
171
200
|
is_running "$pid" || return 1
|
|
@@ -193,6 +222,26 @@ pid_controls_app() {
|
|
|
193
222
|
return 1
|
|
194
223
|
}
|
|
195
224
|
|
|
225
|
+
monitor_controls_app() {
|
|
226
|
+
local pid="$1"
|
|
227
|
+
is_running "$pid" || return 1
|
|
228
|
+
|
|
229
|
+
local cmdline=""
|
|
230
|
+
if [[ -r "/proc/$pid/cmdline" ]]; then
|
|
231
|
+
cmdline="$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null || true)"
|
|
232
|
+
[[ "$cmdline" == *"$SCRIPT_DIR/nterminalctl"* && "$cmdline" == *" supervise"* ]]
|
|
233
|
+
return
|
|
234
|
+
fi
|
|
235
|
+
|
|
236
|
+
if command -v ps >/dev/null 2>&1; then
|
|
237
|
+
cmdline="$(ps -p "$pid" -o command= 2>/dev/null || true)"
|
|
238
|
+
[[ "$cmdline" == *"$SCRIPT_DIR/nterminalctl"* && "$cmdline" == *" supervise"* ]]
|
|
239
|
+
return
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
return 1
|
|
243
|
+
}
|
|
244
|
+
|
|
196
245
|
current_pid() {
|
|
197
246
|
local pid
|
|
198
247
|
pid="$(read_pid || true)"
|
|
@@ -200,6 +249,35 @@ current_pid() {
|
|
|
200
249
|
printf '%s' "$pid"
|
|
201
250
|
return 0
|
|
202
251
|
fi
|
|
252
|
+
|
|
253
|
+
# npm can replace the package directory while the old Node process is still
|
|
254
|
+
# listening. If the pid file is missing, recover by recognizing the port owner
|
|
255
|
+
# as this package runtime before deciding the app is stopped.
|
|
256
|
+
pid="$(port_owner_pid || true)"
|
|
257
|
+
if [[ -n "$pid" && "$(pid_controls_app "$pid" && echo yes || echo no)" == yes ]]; then
|
|
258
|
+
printf '%s' "$pid"
|
|
259
|
+
return 0
|
|
260
|
+
fi
|
|
261
|
+
return 1
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
current_monitor_pid() {
|
|
265
|
+
local pid
|
|
266
|
+
pid="$(read_monitor_pid || true)"
|
|
267
|
+
if [[ -n "$pid" && "$(monitor_controls_app "$pid" && echo yes || echo no)" == yes ]]; then
|
|
268
|
+
printf '%s' "$pid"
|
|
269
|
+
return 0
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
local child_pid parent
|
|
273
|
+
child_pid="$(current_pid || true)"
|
|
274
|
+
if [[ -n "$child_pid" ]]; then
|
|
275
|
+
parent="$(parent_pid "$child_pid" || true)"
|
|
276
|
+
if [[ -n "$parent" && "$(monitor_controls_app "$parent" && echo yes || echo no)" == yes ]]; then
|
|
277
|
+
printf '%s' "$parent"
|
|
278
|
+
return 0
|
|
279
|
+
fi
|
|
280
|
+
fi
|
|
203
281
|
return 1
|
|
204
282
|
}
|
|
205
283
|
|
|
@@ -258,6 +336,14 @@ remove_stale_pid() {
|
|
|
258
336
|
fi
|
|
259
337
|
}
|
|
260
338
|
|
|
339
|
+
remove_stale_monitor_pid() {
|
|
340
|
+
local pid
|
|
341
|
+
pid="$(read_monitor_pid || true)"
|
|
342
|
+
if [[ -n "$pid" && ! "$(monitor_controls_app "$pid" && echo yes || echo no)" == yes ]]; then
|
|
343
|
+
rm -f "$MONITOR_PID_PATH"
|
|
344
|
+
fi
|
|
345
|
+
}
|
|
346
|
+
|
|
261
347
|
node_health_check() {
|
|
262
348
|
"$NODE_BIN" -e '
|
|
263
349
|
const http = require("node:http");
|
|
@@ -272,15 +358,90 @@ request.on("error", () => process.exit(1));
|
|
|
272
358
|
}
|
|
273
359
|
|
|
274
360
|
start_daemon() {
|
|
275
|
-
cd "$APP_DIR"
|
|
276
361
|
if command -v setsid >/dev/null 2>&1; then
|
|
277
|
-
nohup setsid
|
|
362
|
+
nohup setsid bash "$SCRIPT_DIR/nterminalctl" supervise >> "$LOG_PATH" 2>&1 &
|
|
278
363
|
else
|
|
279
|
-
nohup
|
|
364
|
+
nohup bash "$SCRIPT_DIR/nterminalctl" supervise >> "$LOG_PATH" 2>&1 &
|
|
365
|
+
fi
|
|
366
|
+
local monitor_pid="$!"
|
|
367
|
+
disown "$monitor_pid" 2>/dev/null || true
|
|
368
|
+
echo "$monitor_pid" > "$MONITOR_PID_PATH"
|
|
369
|
+
chmod 600 "$MONITOR_PID_PATH" 2>/dev/null || true
|
|
370
|
+
|
|
371
|
+
local pid=""
|
|
372
|
+
local deadline=$((SECONDS + HEALTH_TIMEOUT_SECONDS))
|
|
373
|
+
while (( SECONDS <= deadline )); do
|
|
374
|
+
if ! is_running "$monitor_pid"; then
|
|
375
|
+
return 1
|
|
376
|
+
fi
|
|
377
|
+
pid="$(current_pid || true)"
|
|
378
|
+
[[ -n "$pid" ]] && return 0
|
|
379
|
+
sleep 0.25
|
|
380
|
+
done
|
|
381
|
+
return 1
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
stop_supervised_child() {
|
|
385
|
+
local pid="$1"
|
|
386
|
+
[[ -n "$pid" ]] || return 0
|
|
387
|
+
if ! is_running "$pid"; then
|
|
388
|
+
rm -f "$PID_PATH"
|
|
389
|
+
return 0
|
|
280
390
|
fi
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
391
|
+
kill -TERM "$pid" 2>/dev/null || true
|
|
392
|
+
local deadline=$((SECONDS + STOP_TIMEOUT_SECONDS))
|
|
393
|
+
while (( SECONDS <= deadline )); do
|
|
394
|
+
if ! is_running "$pid"; then
|
|
395
|
+
rm -f "$PID_PATH"
|
|
396
|
+
return 0
|
|
397
|
+
fi
|
|
398
|
+
sleep 0.25
|
|
399
|
+
done
|
|
400
|
+
kill -KILL "$pid" 2>/dev/null || true
|
|
401
|
+
rm -f "$PID_PATH"
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
cmd_supervise() {
|
|
405
|
+
ensure_app_dir
|
|
406
|
+
ensure_env_file
|
|
407
|
+
ensure_runtime
|
|
408
|
+
validate_required_env || die "generate real secrets before starting"
|
|
409
|
+
ensure_directories
|
|
410
|
+
echo "$$" > "$MONITOR_PID_PATH"
|
|
411
|
+
chmod 600 "$MONITOR_PID_PATH" 2>/dev/null || true
|
|
412
|
+
|
|
413
|
+
local child_pid=""
|
|
414
|
+
local stop_requested=0
|
|
415
|
+
supervisor_shutdown() {
|
|
416
|
+
stop_requested=1
|
|
417
|
+
trap - TERM INT
|
|
418
|
+
stop_supervised_child "$child_pid"
|
|
419
|
+
rm -f "$MONITOR_PID_PATH"
|
|
420
|
+
exit 0
|
|
421
|
+
}
|
|
422
|
+
trap supervisor_shutdown TERM INT
|
|
423
|
+
|
|
424
|
+
while true; do
|
|
425
|
+
cd "$APP_DIR"
|
|
426
|
+
"$NODE_BIN" "$RUNTIME_ENTRY" >> "$LOG_PATH" 2>&1 &
|
|
427
|
+
child_pid="$!"
|
|
428
|
+
echo "$child_pid" > "$PID_PATH"
|
|
429
|
+
chmod 600 "$PID_PATH" 2>/dev/null || true
|
|
430
|
+
|
|
431
|
+
set +e
|
|
432
|
+
wait "$child_pid"
|
|
433
|
+
local status="$?"
|
|
434
|
+
set -e
|
|
435
|
+
|
|
436
|
+
rm -f "$PID_PATH"
|
|
437
|
+
if (( stop_requested == 1 )); then
|
|
438
|
+
rm -f "$MONITOR_PID_PATH"
|
|
439
|
+
exit 0
|
|
440
|
+
fi
|
|
441
|
+
|
|
442
|
+
printf '[%s] NTerminal process exited status=%s; restarting in 2s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$status" >> "$LOG_PATH"
|
|
443
|
+
sleep 2
|
|
444
|
+
done
|
|
284
445
|
}
|
|
285
446
|
|
|
286
447
|
start_launchd() {
|
|
@@ -320,8 +481,15 @@ wait_for_health() {
|
|
|
320
481
|
}
|
|
321
482
|
|
|
322
483
|
port_owner_pid() {
|
|
323
|
-
command -v lsof >/dev/null 2>&1
|
|
324
|
-
|
|
484
|
+
if command -v lsof >/dev/null 2>&1; then
|
|
485
|
+
lsof -nP -iTCP:"$PORT" -sTCP:LISTEN -t 2>/dev/null | head -n 1
|
|
486
|
+
return
|
|
487
|
+
fi
|
|
488
|
+
if command -v ss >/dev/null 2>&1; then
|
|
489
|
+
ss -ltnp "sport = :$PORT" 2>/dev/null | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' | head -n 1
|
|
490
|
+
return
|
|
491
|
+
fi
|
|
492
|
+
return 1
|
|
325
493
|
}
|
|
326
494
|
|
|
327
495
|
assert_port_available() {
|
|
@@ -336,23 +504,27 @@ assert_port_available() {
|
|
|
336
504
|
|
|
337
505
|
cmd_status() {
|
|
338
506
|
remove_stale_pid
|
|
507
|
+
remove_stale_monitor_pid
|
|
339
508
|
local pid
|
|
340
509
|
pid="$(current_pid || true)"
|
|
341
510
|
if [[ -n "$pid" ]]; then
|
|
342
511
|
info "NTerminal running pid=$pid url=$(public_url) log=$LOG_PATH"
|
|
343
512
|
return 0
|
|
344
513
|
fi
|
|
514
|
+
local monitor_pid
|
|
515
|
+
monitor_pid="$(current_monitor_pid || true)"
|
|
516
|
+
if [[ -n "$monitor_pid" ]]; then
|
|
517
|
+
info "NTerminal supervisor running pid=$monitor_pid; server is restarting url=$(public_url) log=$LOG_PATH"
|
|
518
|
+
return 4
|
|
519
|
+
fi
|
|
345
520
|
info "NTerminal stopped pid_file=$PID_PATH"
|
|
346
521
|
return 3
|
|
347
522
|
}
|
|
348
523
|
|
|
349
524
|
cmd_start() {
|
|
350
|
-
|
|
351
|
-
ensure_env_file
|
|
352
|
-
ensure_runtime
|
|
353
|
-
validate_required_env || die "generate real secrets before starting"
|
|
354
|
-
ensure_directories
|
|
525
|
+
prepare_start
|
|
355
526
|
remove_stale_pid
|
|
527
|
+
remove_stale_monitor_pid
|
|
356
528
|
|
|
357
529
|
local pid
|
|
358
530
|
pid="$(current_pid || true)"
|
|
@@ -360,6 +532,12 @@ cmd_start() {
|
|
|
360
532
|
info "NTerminal already running pid=$pid url=$(public_url)"
|
|
361
533
|
return 0
|
|
362
534
|
fi
|
|
535
|
+
local monitor_pid
|
|
536
|
+
monitor_pid="$(current_monitor_pid || true)"
|
|
537
|
+
if [[ -n "$monitor_pid" ]]; then
|
|
538
|
+
info "NTerminal supervisor already running pid=$monitor_pid url=$(public_url)"
|
|
539
|
+
return 0
|
|
540
|
+
fi
|
|
363
541
|
|
|
364
542
|
if launchd_controls_app; then
|
|
365
543
|
start_launchd
|
|
@@ -367,12 +545,28 @@ cmd_start() {
|
|
|
367
545
|
fi
|
|
368
546
|
|
|
369
547
|
assert_port_available
|
|
370
|
-
start_daemon
|
|
548
|
+
if ! start_daemon; then
|
|
549
|
+
rm -f "$MONITOR_PID_PATH"
|
|
550
|
+
echo "NTerminal failed to start supervisor. Last log lines:" >&2
|
|
551
|
+
tail -n 40 "$LOG_PATH" >&2 || true
|
|
552
|
+
return 1
|
|
553
|
+
fi
|
|
371
554
|
chmod 600 "$PID_PATH" 2>/dev/null || true
|
|
372
|
-
pid="$(
|
|
555
|
+
pid="$(current_pid || true)"
|
|
556
|
+
if [[ -z "$pid" ]]; then
|
|
557
|
+
rm -f "$MONITOR_PID_PATH"
|
|
558
|
+
echo "NTerminal failed to start supervisor. Last log lines:" >&2
|
|
559
|
+
tail -n 40 "$LOG_PATH" >&2 || true
|
|
560
|
+
return 1
|
|
561
|
+
fi
|
|
373
562
|
|
|
374
563
|
if wait_for_health "$pid"; then
|
|
375
|
-
|
|
564
|
+
monitor_pid="$(current_monitor_pid || true)"
|
|
565
|
+
if [[ -n "$monitor_pid" ]]; then
|
|
566
|
+
info "NTerminal started pid=$pid supervisor=$monitor_pid url=$(public_url) log=$LOG_PATH"
|
|
567
|
+
else
|
|
568
|
+
info "NTerminal started pid=$pid url=$(public_url) log=$LOG_PATH"
|
|
569
|
+
fi
|
|
376
570
|
return 0
|
|
377
571
|
fi
|
|
378
572
|
|
|
@@ -380,7 +574,11 @@ cmd_start() {
|
|
|
380
574
|
if ! is_running "$pid"; then
|
|
381
575
|
exit_hint="process exited during startup"
|
|
382
576
|
fi
|
|
383
|
-
|
|
577
|
+
monitor_pid="$(current_monitor_pid || true)"
|
|
578
|
+
if [[ -n "$monitor_pid" ]]; then
|
|
579
|
+
kill -TERM "$monitor_pid" 2>/dev/null || true
|
|
580
|
+
fi
|
|
581
|
+
rm -f "$PID_PATH" "$MONITOR_PID_PATH"
|
|
384
582
|
echo "NTerminal $exit_hint. Last log lines:" >&2
|
|
385
583
|
tail -n 40 "$LOG_PATH" >&2 || true
|
|
386
584
|
return 1
|
|
@@ -388,13 +586,44 @@ cmd_start() {
|
|
|
388
586
|
|
|
389
587
|
cmd_stop() {
|
|
390
588
|
remove_stale_pid
|
|
589
|
+
remove_stale_monitor_pid
|
|
391
590
|
local pid
|
|
392
591
|
pid="$(current_pid || true)"
|
|
393
|
-
|
|
592
|
+
local monitor_pid
|
|
593
|
+
monitor_pid="$(current_monitor_pid || true)"
|
|
594
|
+
if [[ -z "$pid" && -z "$monitor_pid" ]]; then
|
|
394
595
|
info "NTerminal already stopped"
|
|
395
596
|
return 0
|
|
396
597
|
fi
|
|
397
598
|
|
|
599
|
+
if [[ -n "$monitor_pid" ]]; then
|
|
600
|
+
kill -TERM "$monitor_pid" 2>/dev/null || true
|
|
601
|
+
local monitor_deadline=$((SECONDS + STOP_TIMEOUT_SECONDS))
|
|
602
|
+
while (( SECONDS <= monitor_deadline )); do
|
|
603
|
+
if ! is_running "$monitor_pid"; then
|
|
604
|
+
rm -f "$MONITOR_PID_PATH"
|
|
605
|
+
break
|
|
606
|
+
fi
|
|
607
|
+
sleep 0.25
|
|
608
|
+
done
|
|
609
|
+
if is_running "$monitor_pid"; then
|
|
610
|
+
kill -KILL "$monitor_pid" 2>/dev/null || true
|
|
611
|
+
rm -f "$MONITOR_PID_PATH"
|
|
612
|
+
fi
|
|
613
|
+
|
|
614
|
+
if [[ -n "$pid" && "$(is_running "$pid" && echo yes || echo no)" == yes ]]; then
|
|
615
|
+
stop_supervised_child "$pid"
|
|
616
|
+
fi
|
|
617
|
+
|
|
618
|
+
rm -f "$PID_PATH" "$MONITOR_PID_PATH"
|
|
619
|
+
if [[ -n "$pid" ]]; then
|
|
620
|
+
info "NTerminal stopped pid=$pid supervisor=$monitor_pid"
|
|
621
|
+
else
|
|
622
|
+
info "NTerminal stopped supervisor=$monitor_pid"
|
|
623
|
+
fi
|
|
624
|
+
return 0
|
|
625
|
+
fi
|
|
626
|
+
|
|
398
627
|
kill -TERM "$pid" 2>/dev/null || true
|
|
399
628
|
local deadline=$((SECONDS + STOP_TIMEOUT_SECONDS))
|
|
400
629
|
while (( SECONDS <= deadline )); do
|
|
@@ -415,6 +644,7 @@ cmd_restart() {
|
|
|
415
644
|
if launchd_controls_app; then
|
|
416
645
|
start_launchd
|
|
417
646
|
else
|
|
647
|
+
prepare_start
|
|
418
648
|
cmd_stop >/dev/null
|
|
419
649
|
cmd_start
|
|
420
650
|
fi
|
|
@@ -452,43 +682,17 @@ cmd_logs() {
|
|
|
452
682
|
fi
|
|
453
683
|
}
|
|
454
684
|
|
|
455
|
-
stop_pid_file() {
|
|
456
|
-
local pid_path="$1"
|
|
457
|
-
local pid
|
|
458
|
-
pid="$(read_pid_file "$pid_path" || true)"
|
|
459
|
-
if [[ -z "$pid" ]]; then
|
|
460
|
-
return 0
|
|
461
|
-
fi
|
|
462
|
-
if ! is_running "$pid"; then
|
|
463
|
-
rm -f "$pid_path"
|
|
464
|
-
return 0
|
|
465
|
-
fi
|
|
466
|
-
if ! pid_controls_app "$pid"; then
|
|
467
|
-
rm -f "$pid_path"
|
|
468
|
-
return 0
|
|
469
|
-
fi
|
|
470
|
-
|
|
471
|
-
kill -TERM "$pid" 2>/dev/null || true
|
|
472
|
-
local deadline=$((SECONDS + STOP_TIMEOUT_SECONDS))
|
|
473
|
-
while (( SECONDS <= deadline )); do
|
|
474
|
-
if ! is_running "$pid"; then
|
|
475
|
-
rm -f "$pid_path"
|
|
476
|
-
return 0
|
|
477
|
-
fi
|
|
478
|
-
sleep 0.25
|
|
479
|
-
done
|
|
480
|
-
|
|
481
|
-
kill -KILL "$pid" 2>/dev/null || true
|
|
482
|
-
rm -f "$pid_path"
|
|
483
|
-
}
|
|
484
|
-
|
|
485
685
|
clean_state_paths() {
|
|
486
686
|
local state_path="$1"
|
|
487
687
|
local pid_path="$2"
|
|
488
688
|
local log_path="$3"
|
|
689
|
+
local monitor_pid_path="${4:-}"
|
|
489
690
|
local state_dir
|
|
490
691
|
state_dir="$(dirname "$state_path")"
|
|
491
692
|
rm -f "$state_path" "$pid_path" "$log_path" "$state_dir/update.lock"
|
|
693
|
+
if [[ -n "$monitor_pid_path" ]]; then
|
|
694
|
+
rm -f "$monitor_pid_path"
|
|
695
|
+
fi
|
|
492
696
|
rm -rf "$state_dir/notification-assets"
|
|
493
697
|
}
|
|
494
698
|
|
|
@@ -518,7 +722,7 @@ cmd_clean() {
|
|
|
518
722
|
|
|
519
723
|
local state_dir
|
|
520
724
|
state_dir="$(dirname "$STATE_PATH")"
|
|
521
|
-
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH"
|
|
725
|
+
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH" "$MONITOR_PID_PATH"
|
|
522
726
|
if (( remove_env == 1 )); then
|
|
523
727
|
rm -f "$ENV_FILE"
|
|
524
728
|
fi
|
|
@@ -544,11 +748,11 @@ cmd_uninstall() {
|
|
|
544
748
|
|
|
545
749
|
ensure_app_dir
|
|
546
750
|
unload_launchd_if_controlled
|
|
547
|
-
|
|
751
|
+
cmd_stop >/dev/null
|
|
548
752
|
if (( kill_tmux == 1 )) && command -v tmux >/dev/null 2>&1; then
|
|
549
753
|
tmux -L nterminal kill-server >/dev/null 2>&1 || true
|
|
550
754
|
fi
|
|
551
|
-
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH"
|
|
755
|
+
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH" "$MONITOR_PID_PATH"
|
|
552
756
|
rm -f "$ENV_FILE"
|
|
553
757
|
remove_owned_launchd_plist
|
|
554
758
|
|
|
@@ -609,10 +813,10 @@ cmd_doctor() {
|
|
|
609
813
|
fi
|
|
610
814
|
|
|
611
815
|
ensure_directories
|
|
612
|
-
if [[ -w "$(dirname "$PID_PATH")" && -w "$(dirname "$LOG_PATH")" ]]; then
|
|
613
|
-
echo "ok writable: pid/log directories"
|
|
816
|
+
if [[ -w "$(dirname "$PID_PATH")" && -w "$(dirname "$MONITOR_PID_PATH")" && -w "$(dirname "$LOG_PATH")" ]]; then
|
|
817
|
+
echo "ok writable: pid/monitor/log directories"
|
|
614
818
|
else
|
|
615
|
-
echo "fail writable: pid/log directories"
|
|
819
|
+
echo "fail writable: pid/monitor/log directories"
|
|
616
820
|
failed=1
|
|
617
821
|
fi
|
|
618
822
|
|
|
@@ -634,9 +838,9 @@ cmd_help() {
|
|
|
634
838
|
Usage: nterminal <command>
|
|
635
839
|
|
|
636
840
|
Commands:
|
|
637
|
-
status Show process status. Exit 0 when running, 3 when stopped.
|
|
841
|
+
status Show process status. Exit 0 when running, 3 when stopped, 4 when the supervisor is restarting it.
|
|
638
842
|
start Start the built server in the background.
|
|
639
|
-
stop Stop the managed server with SIGTERM, then SIGKILL after timeout.
|
|
843
|
+
stop Stop the managed server and supervisor with SIGTERM, then SIGKILL after timeout.
|
|
640
844
|
restart Stop and start the server.
|
|
641
845
|
build No-op for package installs; verifies the bundled runtime exists.
|
|
642
846
|
deploy Restart the installed package using the bundled runtime.
|
|
@@ -657,6 +861,7 @@ Environment:
|
|
|
657
861
|
NTERMINAL_ENV_FILE Override .env path.
|
|
658
862
|
NTERMINAL_STATE_PATH Default ~/.nterminal/state.json.
|
|
659
863
|
NTERMINAL_PID_PATH Default ~/.nterminal/nterminal.pid.
|
|
864
|
+
NTERMINAL_MONITOR_PID_PATH Default ~/.nterminal/nterminal.monitor.pid.
|
|
660
865
|
NTERMINAL_LOG_PATH Default ~/.nterminal/nterminal.log.
|
|
661
866
|
NTERMINAL_HEALTH_TIMEOUT_SECONDS Default 15.
|
|
662
867
|
NTERMINAL_STOP_TIMEOUT_SECONDS Default 20.
|
|
@@ -667,6 +872,7 @@ EOF
|
|
|
667
872
|
case "$COMMAND" in
|
|
668
873
|
status) cmd_status "$@" ;;
|
|
669
874
|
start) cmd_start "$@" ;;
|
|
875
|
+
supervise) cmd_supervise "$@" ;;
|
|
670
876
|
stop) cmd_stop "$@" ;;
|
|
671
877
|
restart|reload) cmd_restart "$@" ;;
|
|
672
878
|
build) cmd_build "$@" ;;
|