
























@@ -442,14 +442,23 @@ class NpmUpdateSmoke {
442442ctx: UpdateJobContext,
443443): Promise<void> {
444444const macosExecArgs = this.resolveMacosUpdateExecArgs(ctx);
445-const status = await this.runStreamingToJobLog(
446-"prlctl",
447-["exec", macosVm, ...macosExecArgs, "/bin/bash", "-lc", script],
448-timeoutMs,
449-ctx,
445+const scriptPath = this.writeGuestScript(
446+macosVm,
447+script,
448+"openclaw-parallels-npm-update-macos",
450449);
451-if (status !== 0) {
452-throw new Error(`macOS update command failed with exit code ${status}`);
450+try {
451+const status = await this.runStreamingToJobLog(
452+"prlctl",
453+["exec", macosVm, ...macosExecArgs, "/bin/bash", scriptPath],
454+timeoutMs,
455+ctx,
456+);
457+if (status !== 0) {
458+throw new Error(`macOS update command failed with exit code ${status}`);
459+}
460+} finally {
461+this.removeGuestScript(macosVm, scriptPath);
453462}
454463}
455464@@ -688,15 +697,62 @@ Remove-Item -Path $scriptPath, $logPath, $donePath, $exitPath -Force -ErrorActio
688697timeoutMs: number,
689698ctx: UpdateJobContext,
690699): Promise<void> {
691-const status = await this.runStreamingToJobLog(
692-"prlctl",
693-["exec", this.linuxVm, "/usr/bin/env", "HOME=/root", "bash", "-lc", script],
694-timeoutMs,
695-ctx,
700+const scriptPath = this.writeGuestScript(
701+this.linuxVm,
702+script,
703+"openclaw-parallels-npm-update-linux",
696704);
697-if (status !== 0) {
698-throw new Error(`Linux update command failed with exit code ${status}`);
705+try {
706+const status = await this.runStreamingToJobLog(
707+"prlctl",
708+[
709+"exec",
710+this.linuxVm,
711+"/usr/bin/env",
712+"HOME=/root",
713+"PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/snap/bin",
714+"bash",
715+scriptPath,
716+],
717+timeoutMs,
718+ctx,
719+);
720+if (status !== 0) {
721+throw new Error(`Linux update command failed with exit code ${status}`);
722+}
723+} finally {
724+this.removeGuestScript(this.linuxVm, scriptPath);
725+}
726+}
727+728+private writeGuestScript(vm: string, script: string, prefix: string): string {
729+const scriptPath = `/tmp/${prefix}-${process.pid}-${Date.now()}.sh`;
730+const write = run("prlctl", ["exec", vm, "/usr/bin/tee", scriptPath], {
731+check: false,
732+input: script,
733+quiet: true,
734+timeoutMs: 120_000,
735+});
736+if (write.status !== 0) {
737+throw new Error(`failed to write guest script ${scriptPath}: ${write.stderr.trim()}`);
738+}
739+const chmod = run("prlctl", ["exec", vm, "/bin/chmod", "700", scriptPath], {
740+check: false,
741+quiet: true,
742+timeoutMs: 30_000,
743+});
744+if (chmod.status !== 0) {
745+throw new Error(`failed to chmod guest script ${scriptPath}: ${chmod.stderr.trim()}`);
699746}
747+return scriptPath;
748+}
749+750+private removeGuestScript(vm: string, scriptPath: string): void {
751+run("prlctl", ["exec", vm, "/bin/rm", "-f", scriptPath], {
752+check: false,
753+quiet: true,
754+timeoutMs: 30_000,
755+});
700756}
701757702758private async runStreamingToJobLog(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。