mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-27 15:54:48 +08:00
fix: use shell fallback instead of hardcoded /bin/zsh in LocalSandbox (#939)
* fix: use shell fallback instead of hardcoded /bin/zsh in LocalSandbox Replace hardcoded /bin/zsh executable with dynamic shell detection that falls back through /bin/zsh → /bin/bash → /bin/sh. This fixes skill execution failures in Docker containers (python:3.12-slim) where zsh is not available. Closes #935 * Update backend/src/sandbox/local/local_sandbox.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: atian8179 <atian8179@users.noreply.github.com> Co-authored-by: Willem Jiang <willem.jiang@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -132,13 +133,32 @@ class LocalSandbox(Sandbox):
|
|||||||
|
|
||||||
return pattern.sub(replace_match, command)
|
return pattern.sub(replace_match, command)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_shell() -> str:
|
||||||
|
"""Detect available shell executable with fallback.
|
||||||
|
|
||||||
|
Returns the first available shell in order of preference:
|
||||||
|
/bin/zsh → /bin/bash → /bin/sh → first `sh` found on PATH.
|
||||||
|
Raises a RuntimeError if no suitable shell is found.
|
||||||
|
"""
|
||||||
|
for shell in ("/bin/zsh", "/bin/bash", "/bin/sh"):
|
||||||
|
if os.path.isfile(shell) and os.access(shell, os.X_OK):
|
||||||
|
return shell
|
||||||
|
shell_from_path = shutil.which("sh")
|
||||||
|
if shell_from_path is not None:
|
||||||
|
return shell_from_path
|
||||||
|
raise RuntimeError(
|
||||||
|
"No suitable shell executable found. Tried /bin/zsh, /bin/bash, "
|
||||||
|
"/bin/sh, and `sh` on PATH."
|
||||||
|
)
|
||||||
|
|
||||||
def execute_command(self, command: str) -> str:
|
def execute_command(self, command: str) -> str:
|
||||||
# Resolve container paths in command before execution
|
# Resolve container paths in command before execution
|
||||||
resolved_command = self._resolve_paths_in_command(command)
|
resolved_command = self._resolve_paths_in_command(command)
|
||||||
|
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
resolved_command,
|
resolved_command,
|
||||||
executable="/bin/zsh",
|
executable=self._get_shell(),
|
||||||
shell=True,
|
shell=True,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
|
|||||||
Reference in New Issue
Block a user