querysub 0.211.0 → 0.213.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.211.0",
3
+ "version": "0.213.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -18,7 +18,7 @@ import os from "os";
18
18
  import fs from "fs";
19
19
  import { lazy } from "socket-function/src/caching";
20
20
  import { setGitRef } from "../4-deploy/git";
21
- import { blue, magenta } from "socket-function/src/formatting/logColors";
21
+ import { blue, green, magenta } from "socket-function/src/formatting/logColors";
22
22
  import { shutdown } from "../diagnostics/periodic";
23
23
 
24
24
  const getLiveMachineInfo = measureWrap(async function getLiveMachineInfo() {
@@ -51,20 +51,21 @@ const getTmuxPrefix = lazy(() => {
51
51
  }
52
52
  return "";
53
53
  });
54
- function textTableLineToObj(text: string): Record<string, string> {
54
+ function textTableLineToObj(text: string): Record<string, string>[] {
55
55
  /*
56
56
  PID PPID PGID WINPID TTY UID STIME COMMAND
57
57
  1312 1284 1312 56996 pty2 197609 09:24:47 /usr/bin/bash
58
+ 1313 1284 1313 56997 pty3 197609 09:24:48 /usr/bin/vim
58
59
  =>
59
- { PID: "1312", PPID: "1284", ...}
60
+ [{ PID: "1312", PPID: "1284", ...}, { PID: "1313", PPID: "1284", ...}]
60
61
  */
61
62
  let lines = text.trim().split("\n").filter(line => line.trim().length > 0);
62
63
  if (lines.length < 2) {
63
- return {};
64
+ return [];
64
65
  }
65
66
 
66
67
  let headerLine = lines[0];
67
- let dataLine = lines[1];
68
+ let dataLines = lines.slice(1);
68
69
 
69
70
  // Parse column positions from header
70
71
  let columns: { name: string; start: number; end: number }[] = [];
@@ -83,55 +84,70 @@ function textTableLineToObj(text: string): Record<string, string> {
83
84
  currentPos = start + word.length;
84
85
  }
85
86
 
86
- // Extract values from data line
87
- let result: Record<string, string> = {};
88
- for (let column of columns) {
89
- let value = dataLine.substring(column.start, column.end).trim();
90
- result[column.name] = value;
87
+ // Extract values from all data lines
88
+ let results: Record<string, string>[] = [];
89
+ for (let dataLine of dataLines) {
90
+ let result: Record<string, string> = {};
91
+ for (let column of columns) {
92
+ let value = dataLine.substring(column.start, column.end).trim();
93
+ result[column.name] = value;
94
+ }
95
+ results.push(result);
91
96
  }
92
97
 
93
- return result;
98
+ return results;
94
99
  }
95
- async function getTmuxProcessInfo(pid: string) {
100
+ async function getLinuxProcessInfo(pid: string) {
96
101
  try {
97
- let psInfo = await runPromise(`ps -p ${pid}`);
98
- let obj = textTableLineToObj(psInfo) as { PPID: string; CMD: string };
102
+ let extraArgs = os.platform() !== "win32" && " -o ppid,cmd" || "";
103
+ let psInfo = await runPromise(`ps -p ${pid}${extraArgs}`);
104
+ let results = textTableLineToObj(psInfo);
105
+ let obj = results[0] as { PPID: string; CMD: string };
99
106
  return obj;
100
107
  } catch (e: any) {
101
108
  console.warn(`Error getting tmux process info for ${pid}: ${e.stack}`);
102
109
  return undefined;
103
110
  }
104
111
  }
105
- async function getTmuxPPID(pid: string) {
106
- try {
107
- let psInfo = await runPromise(`ps -p ${pid}`);
108
- let obj = textTableLineToObj(psInfo) as { PPID: string };
109
- return obj.PPID;
110
- } catch (e: any) {
111
- console.warn(`Error getting ppid for ${pid}: ${e.stack}`);
112
- return "0";
112
+ const getLinuxChildPids = measureWrap(async function getLinuxChildPids(pid: string): Promise<{ PID: string; PPID: string; CMD: string }[]> {
113
+ let prefix = getTmuxPrefix();
114
+ if (os.platform() === "win32") {
115
+ let table = await runPromise(`${prefix}ps`);
116
+ let obj = textTableLineToObj(table) as { PID: string; PPID: string; CMD: string }[];
117
+ return obj.filter(x => x.PPID === pid);
118
+ } else {
119
+ let table = await runPromise(`ps -eo pid,ppid,cmd`);
120
+ let obj = textTableLineToObj(table) as { PPID: string; PID: string; CMD: string }[];
121
+ return obj.filter(x => x.PPID === pid);
113
122
  }
114
- }
123
+ });
115
124
  const isScreenRunningProcess = measureWrap(async function isScreenRunningProcess(pid: string): Promise<boolean> {
116
125
  try {
117
- let ppid = (await getTmuxProcessInfo(pid))?.PPID;
118
- if (!ppid) return false;
119
- let parentCommand = (await getTmuxProcessInfo(ppid))?.CMD;
120
- let execName = parentCommand?.split("/").at(-1);
121
- console.log(`Screen for pid ${pid} is running ${execName}`);
122
- return execName !== "tmux";
126
+ let childPids = await getLinuxChildPids(pid);
127
+ let bashPid = childPids.find(x => x.CMD.includes("bash"));
128
+ if (!bashPid) {
129
+ console.error(`Screen pid ${pid} isn't even running bash? What? We can't check if it's running the process or not, so returning true, which disables crash detection... is running ${JSON.stringify(childPids)}`);
130
+ return true;
131
+ }
132
+ let bashChildPids = await getLinuxChildPids(bashPid.PID);
133
+ for (let childPid of bashChildPids) {
134
+ console.log(`Screen pid ${pid} is running ${childPid.CMD}`);
135
+ return true;
136
+ }
137
+ return false;
123
138
  } catch (e: any) {
124
139
  console.warn(`Error checking if screen is running for ${pid}: ${e.stack}`);
125
140
  return false;
126
141
  }
127
142
  });
128
- const getScreenState = measureWrap(async function getScreenState(): Promise<{
143
+ const getScreenState = measureWrap(async function getScreenState(populateIsProcessRunning: boolean = true): Promise<{
129
144
  screenName: string;
130
145
  isProcessRunning: boolean;
131
146
  pid: string;
132
147
  }[]> {
133
148
  const prefix = getTmuxPrefix();
134
149
  const delimit = "::::";
150
+ // tmux list-panes -a -F "#{session_name}::::#{pane_pid}"
135
151
  let screenList = (await runPromise(`${prefix}tmux list-panes -a -F "#{session_name}${delimit}#{pane_pid}"`))
136
152
  .split("\n")
137
153
  .filter(x => x.includes(delimit))
@@ -143,9 +159,11 @@ const getScreenState = measureWrap(async function getScreenState(): Promise<{
143
159
  .filter(x => x.screenName.endsWith(SCREEN_SUFFIX))
144
160
  ;
145
161
 
146
- await Promise.all(screenList.map(async x => {
147
- x.isProcessRunning = await isScreenRunningProcess(x.pid);
148
- }));
162
+ if (populateIsProcessRunning) {
163
+ await Promise.all(screenList.map(async x => {
164
+ x.isProcessRunning = await isScreenRunningProcess(x.pid);
165
+ }));
166
+ }
149
167
 
150
168
  return screenList;
151
169
  });
@@ -241,7 +259,10 @@ const resyncServices = runInSerial(measureWrap(async function resyncServices() {
241
259
  let sameParameters = prevParameters === newParametersString;
242
260
  let screenIsRunning = screenStateMap.get(screenName)?.isProcessRunning;
243
261
 
244
- if (sameParameters && screenIsRunning) continue;
262
+ if (sameParameters && screenIsRunning) {
263
+ console.log(green(`Verified ${magenta(config.serviceId)} is running`));
264
+ continue;
265
+ }
245
266
 
246
267
  console.log(`Resyncing service ${magenta(config.serviceId)}`);
247
268
 
@@ -252,20 +273,18 @@ const resyncServices = runInSerial(measureWrap(async function resyncServices() {
252
273
  command: config.parameters.command,
253
274
  });
254
275
  await delay(2000);
255
- let newScreens = await getScreenState();
276
+ let newScreens = await getScreenState(false);
256
277
  let foundScreen = newScreens.find(x => x.screenName === screenName);
257
278
  if (!foundScreen) {
258
279
  console.error(`Just created screen ${screenName}, but it's not in the list of screens!`);
259
280
  }
260
281
  let isRunning = foundScreen && await isScreenRunningProcess(foundScreen.pid);
261
- if (!isRunning) {
262
- console.error(`Screen ${screenName} is not running, but it's in the list of screens`);
263
- }
264
282
  if (!isRunning) {
265
283
  let prefix = getTmuxPrefix();
266
284
  let logs = await runPromise(`${prefix}tmux capture-pane -t ${screenName} -p`);
267
285
  throw new Error(`${logs}\n\nService ${magenta(config.serviceId)} is not running after starting. Trying again in ${formatTime(MACHINE_RESYNC_INTERVAL)}, or on next change. Last logs above.`);
268
286
  }
287
+ console.log(green(`Service ${magenta(config.serviceId)} is verified to be running after starting.`));
269
288
 
270
289
  machineInfo.services[config.serviceId] = {
271
290
  lastLaunchedTime: Date.now(),
@@ -21,6 +21,7 @@
21
21
 
22
22
  5) OH! Also setup swap usage on the machine, as it isn't by default often?
23
23
 
24
+ 6) Test again on a new server... I think something might be blocking on user input? Hmm...
24
25
 
25
26
 
26
27
 
@@ -1,6 +1,6 @@
1
1
  import child_process from "child_process";
2
2
  import path from "path";
3
- import { red } from "socket-function/src/formatting/logColors";
3
+ import { blue, red } from "socket-function/src/formatting/logColors";
4
4
 
5
5
  export const runAsync = runPromise;
6
6
  export async function runPromise(command: string, config?: {
@@ -10,6 +10,7 @@ export async function runPromise(command: string, config?: {
10
10
  nothrow?: boolean;
11
11
  }) {
12
12
  return new Promise<string>((resolve, reject) => {
13
+ console.log(">" + blue(command));
13
14
  const childProc = child_process.spawn(command, {
14
15
  shell: true,
15
16
  cwd: config?.cwd,