fix(agent): give launchd units a log sink (StandardOut/ErrorPath)
launchd has no default log destination (unlike systemd's journald), so a unit
that fails to start (bare node, missing env) was silent — which hid the EX_CONFIG
+ loadConfig failures during this deploy. Route both units' stdout+stderr to
<stateDir>/{base-app,agent}.log. 281 tests pass.
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
* - FIX M-host-2service: base-app env (BIND_HOST/ALLOWED_ORIGINS/PORT/…) is routed to the
|
* - FIX M-host-2service: base-app env (BIND_HOST/ALLOWED_ORIGINS/PORT/…) is routed to the
|
||||||
* base-app unit ONLY; the agent unit (which supervises frpc) never carries it.
|
* base-app unit ONLY; the agent unit (which supervises frpc) never carries it.
|
||||||
*/
|
*/
|
||||||
import { dirname } from 'node:path'
|
import { dirname, join } from 'node:path'
|
||||||
import type { AgentConfig } from '../config/agentConfig.js'
|
import type { AgentConfig } from '../config/agentConfig.js'
|
||||||
import {
|
import {
|
||||||
agentLabel,
|
agentLabel,
|
||||||
@@ -225,9 +225,15 @@ export async function installService(
|
|||||||
|
|
||||||
if (platform === 'launchd') {
|
if (platform === 'launchd') {
|
||||||
const baseAppPath = launchdPlistPath(deps.homedir(), baseAppLabel())
|
const baseAppPath = launchdPlistPath(deps.homedir(), baseAppLabel())
|
||||||
deps.writeFile(baseAppPath, buildLaunchdPlist(baseAppExec, baseAppEnvWithPath, baseAppLabel()))
|
deps.writeFile(
|
||||||
|
baseAppPath,
|
||||||
|
buildLaunchdPlist(baseAppExec, baseAppEnvWithPath, baseAppLabel(), join(cfg.stateDir, 'base-app.log')),
|
||||||
|
)
|
||||||
const agentPath = launchdPlistPath(deps.homedir(), agentLabel())
|
const agentPath = launchdPlistPath(deps.homedir(), agentLabel())
|
||||||
deps.writeFile(agentPath, buildLaunchdPlist([nodePath, bin, 'run'], agentEnv, agentLabel()))
|
deps.writeFile(
|
||||||
|
agentPath,
|
||||||
|
buildLaunchdPlist([nodePath, bin, 'run'], agentEnv, agentLabel(), join(cfg.stateDir, 'agent.log')),
|
||||||
|
)
|
||||||
for (const path of [baseAppPath, agentPath]) {
|
for (const path of [baseAppPath, agentPath]) {
|
||||||
const { cmd, args } = launchdLoadCommand(path)
|
const { cmd, args } = launchdLoadCommand(path)
|
||||||
await deps.runCommand(cmd, args)
|
await deps.runCommand(cmd, args)
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export function buildLaunchdPlist(
|
|||||||
programArguments: readonly string[],
|
programArguments: readonly string[],
|
||||||
env: ServiceEnv = {},
|
env: ServiceEnv = {},
|
||||||
label: string = AGENT_LABEL,
|
label: string = AGENT_LABEL,
|
||||||
|
logPath?: string,
|
||||||
): string {
|
): string {
|
||||||
return [
|
return [
|
||||||
'<?xml version="1.0" encoding="UTF-8"?>',
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||||
@@ -91,6 +92,16 @@ export function buildLaunchdPlist(
|
|||||||
' <true/>',
|
' <true/>',
|
||||||
' <key>KeepAlive</key>',
|
' <key>KeepAlive</key>',
|
||||||
' <true/>',
|
' <true/>',
|
||||||
|
// launchd's default has no log sink (unlike systemd's journald), so a crashing unit is silent.
|
||||||
|
// Route stdout+stderr to a file so `pair --install` failures are diagnosable out of the box.
|
||||||
|
...(logPath !== undefined
|
||||||
|
? [
|
||||||
|
' <key>StandardOutPath</key>',
|
||||||
|
` <string>${escapeXml(logPath)}</string>`,
|
||||||
|
' <key>StandardErrorPath</key>',
|
||||||
|
` <string>${escapeXml(logPath)}</string>`,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
...environmentVariablesBlock(env),
|
...environmentVariablesBlock(env),
|
||||||
'</dict>',
|
'</dict>',
|
||||||
'</plist>',
|
'</plist>',
|
||||||
|
|||||||
Reference in New Issue
Block a user