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.
@@ -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-2oIP_yU8.js"></script>
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`], cwd, packageUpdateTimeoutMs);
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 on this server.";
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 on this server.';
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,8GAA8G,CAAC;AAEjH,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,8BAA8B;QACnE,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"}
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"}
@@ -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. |
@@ -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
 
@@ -13,7 +13,7 @@ nterminal restart
13
13
  nterminal stop
14
14
  ```
15
15
 
16
- The script starts the built server in the background, writes a PID file, appends logs, waits for the local health endpoint, and stops the real Node PID so PTY cleanup can run.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nterminal",
3
- "version": "1.2.16",
3
+ "version": "1.2.18",
4
4
  "license": "GPL-3.0-only",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.7",
@@ -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 "$NODE_BIN" "$RUNTIME_ENTRY" >> "$LOG_PATH" 2>&1 &
362
+ nohup setsid bash "$SCRIPT_DIR/nterminalctl" supervise >> "$LOG_PATH" 2>&1 &
278
363
  else
279
- nohup "$NODE_BIN" "$RUNTIME_ENTRY" >> "$LOG_PATH" 2>&1 &
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
- local pid="$!"
282
- disown "$pid" 2>/dev/null || true
283
- echo "$pid" > "$PID_PATH"
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 || return 1
324
- lsof -nP -iTCP:"$PORT" -sTCP:LISTEN -t 2>/dev/null | head -n 1
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
- ensure_app_dir
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="$(read_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
- info "NTerminal started pid=$pid url=$(public_url) log=$LOG_PATH"
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
- rm -f "$PID_PATH"
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
- if [[ -z "$pid" ]]; then
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
- stop_pid_file "$PID_PATH"
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 "$@" ;;