(exe: string)
| 115 | `& '${exe}' daemon run --foreground --port ${PORT} --hostname 127.0.0.1`; |
| 116 | |
| 117 | const startPredecessor = async (exe: string): Promise<PredecessorHandle> => { |
| 118 | if (guestOs() !== "windows") { |
| 119 | await ssh( |
| 120 | `nohup ${exe} daemon run --foreground --port ${PORT} --hostname 127.0.0.1 >/tmp/takeover-predecessor.log 2>&1 &`, |
| 121 | ); |
| 122 | return { |
| 123 | close: () => {}, |
| 124 | diagnostics: async () => |
| 125 | (await ssh("cat /tmp/takeover-predecessor.log 2>/dev/null || true")).stdout.trim(), |
| 126 | }; |
| 127 | } |
| 128 | |
| 129 | const invocation = sshInvocation(windowsPredecessorCommand(exe)); |
| 130 | const child: ChildProcessWithoutNullStreams = spawn(invocation.command, [...invocation.args], { |
| 131 | stdio: ["ignore", "pipe", "pipe"], |
| 132 | }); |
| 133 | let stdout = ""; |
| 134 | let stderr = ""; |
| 135 | let exit: string | null = null; |
| 136 | child.stdout.on("data", (chunk: Buffer) => { |
| 137 | stdout = appendChunk(stdout, chunk); |
| 138 | }); |
| 139 | child.stderr.on("data", (chunk: Buffer) => { |
| 140 | stderr = appendChunk(stderr, chunk); |
| 141 | }); |
| 142 | child.on("error", (error) => { |
| 143 | exit = `spawn error: ${error.message}`; |
| 144 | }); |
| 145 | child.on("exit", (code, signal) => { |
| 146 | exit = `exit code ${code ?? "<null>"} signal ${signal ?? "<null>"}`; |
| 147 | }); |
| 148 | |
| 149 | return { |
| 150 | close: () => { |
| 151 | if (!child.killed) child.kill(); |
| 152 | }, |
| 153 | diagnostics: async () => |
| 154 | [`predecessor ssh: ${exit ?? "still running"}`, `stdout:\n${stdout}`, `stderr:\n${stderr}`] |
| 155 | .join("\n") |
| 156 | .trim(), |
| 157 | }; |
| 158 | }; |
| 159 | |
| 160 | const installServiceCommand = (exe: string): string => |
| 161 | guestOs() === "windows" |
no test coverage detected