MCPcopy Index your code
hub / github.com/coder/mux / exec

Function exec

src/node/runtime/RemoteRuntime.ts:100–339  ·  view source on GitHub ↗

* Execute command with streaming I/O. * Shared implementation that delegates process spawning to subclass.

(command: string, options: ExecOptions)

Source from the content-addressed store, hash-verified

98 * Shared implementation that delegates process spawning to subclass.
99 */
100 async exec(command: string, options: ExecOptions): Promise<ExecStream> {
101 const startTime = performance.now();
102
103 // Short-circuit if already aborted
104 if (options.abortSignal?.aborted) {
105 throw new RuntimeError("Operation aborted before execution", "exec");
106 }
107
108 // Build command parts
109 const parts: string[] = [];
110
111 // Add cd command
112 parts.push(this.cdCommand(options.cwd));
113
114 // Add environment variable exports (user env first, then non-interactive overrides)
115 const envVars = { ...options.env, ...NON_INTERACTIVE_ENV_VARS };
116 for (const [key, value] of Object.entries(envVars)) {
117 parts.push(buildShellExport(key, value, (envValue) => shescape.quote(envValue)));
118 }
119
120 // Add the actual command
121 parts.push(command);
122
123 // Join all parts with && to ensure each step succeeds before continuing
124 let fullCommand = parts.join(" && ");
125
126 // Wrap in bash for consistent shell behavior
127 fullCommand = `bash -c ${shescape.quote(fullCommand)}`;
128
129 // Optionally wrap with timeout
130 if (options.timeout !== undefined) {
131 const remoteTimeout = Math.ceil(options.timeout) + 1;
132 fullCommand = `timeout -s KILL ${remoteTimeout} ${fullCommand}`;
133 }
134
135 // Spawn the remote process (SSH or Docker)
136 const timeoutMs = options.timeout !== undefined ? options.timeout * 1000 : undefined;
137 const deadlineMs = timeoutMs !== undefined ? Date.now() + timeoutMs : undefined;
138 const spawnResult = await this.spawnRemoteProcess(fullCommand, {
139 ...options,
140 deadlineMs,
141 });
142 const { process: childProcess } = spawnResult;
143
144 // Short-lived commands can close stdin before writes/close complete.
145 if (childProcess.stdin) {
146 attachStreamErrorHandler(childProcess.stdin, `${this.commandPrefix} stdin`, {
147 logger: log,
148 });
149 }
150
151 // Wrap in DisposableProcess for cleanup
152 const disposable = new DisposableProcess(childProcess);
153
154 // Track if we killed the process due to timeout or abort
155 let timedOut = false;
156 let aborted = false;
157

Callers 2

syncProjectViaGitBundleFunction · 0.70
execAsyncFunction · 0.50

Calls 15

buildShellExportFunction · 0.90
attachStreamErrorHandlerFunction · 0.90
rejectFunction · 0.85
onMethod · 0.80
removeEventListenerMethod · 0.80
debugMethod · 0.80
onAbortFunction · 0.70
onErrorFunction · 0.70
pushMethod · 0.65
spawnRemoteProcessMethod · 0.65
onExitMethod · 0.65
killMethod · 0.65

Tested by

no test coverage detected