

















@@ -58,6 +58,28 @@ function throwIfFailed(label: string, result: CommandResult, check: boolean | un
5858throw new Error(`${label} failed with exit code ${result.status}`);
5959}
606061+const POSIX_GUEST_SCRIPT_CLEANUP_TIMEOUT_MS = 30_000;
62+63+function appendCommandResult(phases: PhaseRunner, result: CommandResult): void {
64+phases.append(result.stdout);
65+phases.append(result.stderr);
66+}
67+68+function cleanupPosixGuestScript(phases: PhaseRunner, transportArgs: string[]): void {
69+try {
70+appendCommandResult(
71+phases,
72+run("prlctl", transportArgs, {
73+check: false,
74+quiet: true,
75+timeoutMs: POSIX_GUEST_SCRIPT_CLEANUP_TIMEOUT_MS,
76+}),
77+);
78+} catch {
79+// Cleanup must not hide the command failure that made the phase useful.
80+}
81+}
82+6183export async function runWindowsBackgroundPowerShell(
6284options: WindowsBackgroundPowerShellOptions,
6385): Promise<void> {
@@ -354,48 +376,36 @@ export class LinuxGuest {
354376) {}
355377356378exec(args: string[], options: GuestExecOptions = {}): string {
357-const result = run(
358-"prlctl",
359-["exec", this.vmName, "/usr/bin/env", "HOME=/root", "OPENCLAW_ALLOW_ROOT=1", ...args],
360-{
361-check: false,
362-input: options.input,
363-quiet: true,
364-timeoutMs: this.phases.remainingTimeoutMs(options.timeoutMs),
365-},
366-);
379+const result = run("prlctl", this.transportArgs(args), {
380+check: false,
381+input: options.input,
382+quiet: true,
383+timeoutMs: this.phases.remainingTimeoutMs(options.timeoutMs),
384+});
367385this.phases.append(result.stdout);
368386this.phases.append(result.stderr);
369387throwIfFailed("Linux guest command", result, options.check);
370388return result.stdout.trim();
371389}
372390391+private transportArgs(args: string[]): string[] {
392+return ["exec", this.vmName, "/usr/bin/env", "HOME=/root", "OPENCLAW_ALLOW_ROOT=1", ...args];
393+}
394+373395bash(script: string): string {
374396const scriptPath = `/tmp/${guestScriptName("sh")}`;
375-const write = run(
376-"prlctl",
377-[
378-"exec",
379-this.vmName,
380-"/usr/bin/env",
381-"HOME=/root",
382-"OPENCLAW_ALLOW_ROOT=1",
383-"dd",
384-`of=${scriptPath}`,
385-"bs=1048576",
386-],
387-{
397+try {
398+const write = run("prlctl", this.transportArgs(["dd", `of=${scriptPath}`, "bs=1048576"]), {
399+check: false,
388400input: `umask 022\n${script}`,
389401quiet: true,
390402timeoutMs: this.phases.remainingTimeoutMs(),
391-},
392-);
393-this.phases.append(write.stdout);
394-this.phases.append(write.stderr);
395-try {
403+});
404+appendCommandResult(this.phases, write);
405+throwIfFailed("Linux guest script write", write, undefined);
396406return this.exec(["bash", scriptPath]);
397407} finally {
398-this.exec(["rm", "-f", scriptPath], { check: false });
408+cleanupPosixGuestScript(this.phases, this.transportArgs(["/bin/rm", "-f", scriptPath]));
399409}
400410}
401411}
@@ -420,29 +430,31 @@ export class MacosGuest {
420430return this.run(args, options).stdout.trim();
421431}
422432423-run(args: string[], options: MacosGuestOptions = {}): CommandResult {
424-const envArgs = Object.entries({ PATH: this.input.path, ...options.env }).map(
433+private transportArgs(args: string[], env: Record<string, string> = {}): string[] {
434+const envArgs = Object.entries({ PATH: this.input.path, ...env }).map(
425435([key, value]) => `${key}=${value}`,
426436);
427437const user = this.input.getUser();
428-const transportArgs =
429-this.input.getTransport() === "sudo"
430- ? [
431-"exec",
432-this.input.vmName,
433-"/usr/bin/sudo",
434-"-H",
435-"-u",
436-user,
437-"/usr/bin/env",
438-`HOME=${this.input.resolveDesktopHome(user)}`,
439-`USER=${user}`,
440-`LOGNAME=${user}`,
441- ...envArgs,
442- ...args,
443-]
444- : ["exec", this.input.vmName, "--current-user", "/usr/bin/env", ...envArgs, ...args];
445-const result = run("prlctl", transportArgs, {
438+return this.input.getTransport() === "sudo"
439+ ? [
440+"exec",
441+this.input.vmName,
442+"/usr/bin/sudo",
443+"-H",
444+"-u",
445+user,
446+"/usr/bin/env",
447+`HOME=${this.input.resolveDesktopHome(user)}`,
448+`USER=${user}`,
449+`LOGNAME=${user}`,
450+ ...envArgs,
451+ ...args,
452+]
453+ : ["exec", this.input.vmName, "--current-user", "/usr/bin/env", ...envArgs, ...args];
454+}
455+456+run(args: string[], options: MacosGuestOptions = {}): CommandResult {
457+const result = run("prlctl", this.transportArgs(args, options.env), {
446458check: false,
447459input: options.input,
448460quiet: true,
@@ -456,13 +468,13 @@ export class MacosGuest {
456468457469sh(script: string, env: Record<string, string> = {}): string {
458470const scriptPath = `/tmp/${guestScriptName("sh")}`;
459-this.exec(["/bin/dd", `of=${scriptPath}`, "bs=1048576"], {
460-input: `umask 022\n${script}`,
461-});
462471try {
472+this.exec(["/bin/dd", `of=${scriptPath}`, "bs=1048576"], {
473+input: `umask 022\n${script}`,
474+});
463475return this.exec(["/bin/bash", scriptPath], { env });
464476} finally {
465-this.exec(["/bin/rm", "-f", scriptPath], { check: false });
477+cleanupPosixGuestScript(this.phases, this.transportArgs(["/bin/rm", "-f", scriptPath]));
466478}
467479}
468480}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。