querysub 0.210.0 → 0.212.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.210.0",
3
+ "version": "0.212.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",
@@ -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,43 +84,57 @@ 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...`);
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;
@@ -128,9 +143,11 @@ const isScreenRunningProcess = measureWrap(async function isScreenRunningProcess
128
143
  const getScreenState = measureWrap(async function getScreenState(): Promise<{
129
144
  screenName: string;
130
145
  isProcessRunning: boolean;
146
+ pid: string;
131
147
  }[]> {
132
148
  const prefix = getTmuxPrefix();
133
149
  const delimit = "::::";
150
+ // tmux list-panes -a -F "#{session_name}::::#{pane_pid}"
134
151
  let screenList = (await runPromise(`${prefix}tmux list-panes -a -F "#{session_name}${delimit}#{pane_pid}"`))
135
152
  .split("\n")
136
153
  .filter(x => x.includes(delimit))
@@ -251,7 +268,12 @@ const resyncServices = runInSerial(measureWrap(async function resyncServices() {
251
268
  command: config.parameters.command,
252
269
  });
253
270
  await delay(2000);
254
- let isRunning = await isScreenRunningProcess(screenName);
271
+ let newScreens = await getScreenState();
272
+ let foundScreen = newScreens.find(x => x.screenName === screenName);
273
+ if (!foundScreen) {
274
+ console.error(`Just created screen ${screenName}, but it's not in the list of screens!`);
275
+ }
276
+ let isRunning = foundScreen && await isScreenRunningProcess(foundScreen.pid);
255
277
  if (!isRunning) {
256
278
  let prefix = getTmuxPrefix();
257
279
  let logs = await runPromise(`${prefix}tmux capture-pane -t ${screenName} -p`);
@@ -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,