Files
Netcatty/domain/systemManager/dockerShell.ts
陈大猫 ecadc1fc2d
Some checks failed
build-packages / dedupe push run (push) Has been cancelled
build-packages / dedupe result (push) Has been cancelled
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-x64' || 'build-linux-x64' }} (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-arm64' || 'build-linux-arm64' }} (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
[codex] Enable sudo fallback for Docker panel (#1466)
* Enable sudo fallback for Docker panel

* Prefer sudo for Docker panel commands

* Use pending saved sudo password immediately

* Try plain Docker before sudo fallback

* Detect Docker before sudo fallback

* Add sudo fallback for Docker popup commands

* Harden Docker popup sudo fallback
2026-06-14 10:47:21 +08:00

53 lines
2.2 KiB
TypeScript

/** Sanitize Docker container/image IDs — must match electron/bridges/systemManager/dockerOps.cjs */
export function sanitizeDockerContainerId(id: string): string {
return String(id || '').replace(/[^a-zA-Z0-9]/g, '').slice(0, 64);
}
const CLEAR_STARTUP_OUTPUT = "printf '\\033[H\\033[2J\\033[3J';";
function shQuote(value: string): string {
return `'${String(value).replace(/'/g, `'"'"'`)}'`;
}
function buildDockerCommandWithSudoFallback(containerId: string, dockerArgs: string): string {
const plainCommand = `docker ${dockerArgs}`;
const sudoCommand = `sudo ${plainCommand}`;
const script = [
CLEAR_STARTUP_OUTPUT,
`_nc_docker_err=$(docker inspect ${containerId} 2>&1 >/dev/null);`,
'_nc_docker_status=$?;',
`if [ "$_nc_docker_status" -eq 0 ]; then exec ${plainCommand}; fi;`,
'_nc_docker_lc=$(printf \'%s\' "$_nc_docker_err" | tr \'[:upper:]\' \'[:lower:]\');',
'case "$_nc_docker_lc" in',
[
'*permission\\ denied*docker\\ daemon*',
'*docker\\ daemon*permission\\ denied*',
'*permission\\ denied*docker.sock*',
'*docker.sock*permission\\ denied*',
'*permission\\ denied*/var/run/docker.sock*',
'*/var/run/docker.sock*permission\\ denied*',
'*permission\\ denied*connect\\ to\\ the\\ docker\\ daemon*',
'*connect\\ to\\ the\\ docker\\ daemon*permission\\ denied*',
].join('|') + `) exec ${sudoCommand} ;;`,
'*) printf \'%s\\n\' "$_nc_docker_err" >&2; exit "$_nc_docker_status" ;;',
'esac',
].join(' ');
return `sh -c ${shQuote(script)}`;
}
/** Interactive shell into a container — prefer bash, fall back to sh. */
export function buildDockerExecShellCommand(containerId: string): string {
const safeId = sanitizeDockerContainerId(containerId);
if (!safeId) return 'echo "Invalid container id"';
return buildDockerCommandWithSudoFallback(
safeId,
`exec -it ${safeId} sh -c 'command -v bash >/dev/null 2>&1 && exec bash || exec sh'`,
);
}
export function buildDockerLogsCommand(containerId: string): string {
const safeId = sanitizeDockerContainerId(containerId);
if (!safeId) return 'echo "Invalid container id"';
return buildDockerCommandWithSudoFallback(safeId, `logs -f --tail 200 ${safeId}`);
}