fix: run WARP package scripts outside sandbox

This commit is contained in:
Андрей Бобырев
2026-06-05 19:50:08 +03:00
parent f9522bf672
commit f14ea6d8bc

30
app.py
View File

@@ -303,13 +303,30 @@ def run_script(path: str, extra_env=None):
env = os.environ.copy() env = os.environ.copy()
if extra_env: if extra_env:
env.update(extra_env) env.update(extra_env)
cmd = [path]
runner = "direct"
if shutil.which("systemd-run") and os.geteuid() == 0:
unit = "warp-webui-script-" + datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
cmd = [
"systemd-run",
"--wait",
"--pipe",
"--collect",
"--quiet",
f"--unit={unit}",
]
for key, value in (extra_env or {}).items():
cmd.append(f"--setenv={key}={value}")
cmd.append(path)
runner = "systemd-run"
start = time.time() start = time.time()
proc = subprocess.run([path], shell=False, capture_output=True, text=True, timeout=600, env=env) proc = subprocess.run(cmd, shell=False, capture_output=True, text=True, timeout=900, env=env)
dur_ms = int((time.time() - start) * 1000) dur_ms = int((time.time() - start) * 1000)
log_event( log_event(
"info", "info",
"script_executed", "script_executed",
path=path, path=path,
runner=runner,
returncode=proc.returncode, returncode=proc.returncode,
duration_ms=dur_ms, duration_ms=dur_ms,
stdout_tail=(proc.stdout or "")[-2000:], stdout_tail=(proc.stdout or "")[-2000:],
@@ -319,6 +336,7 @@ def run_script(path: str, extra_env=None):
200 if proc.returncode == 0 else 500, 200 if proc.returncode == 0 else 500,
{ {
"path": path, "path": path,
"runner": runner,
"result_code": proc.returncode, "result_code": proc.returncode,
"stdout": (proc.stdout or "").strip(), "stdout": (proc.stdout or "").strip(),
"stderr": (proc.stderr or "").strip(), "stderr": (proc.stderr or "").strip(),
@@ -1228,6 +1246,7 @@ INDEX_HTML = r"""<!doctype html>
<script> <script>
const el = (id) => document.getElementById(id); const el = (id) => document.getElementById(id);
let authRestartUntil = 0;
function badge(text, ok=null) { function badge(text, ok=null) {
const b = el('statusBadge'); const b = el('statusBadge');
b.textContent = text; b.textContent = text;
@@ -1258,7 +1277,13 @@ async function refreshAuthConfig() {
setText('authUser', cfg.user); setText('authUser', cfg.user);
setText('authEnvFile', cfg.env_file); setText('authEnvFile', cfg.env_file);
if (!el('authUserInput').value) el('authUserInput').value = cfg.user || ''; if (!el('authUserInput').value) el('authUserInput').value = cfg.user || '';
} catch (e) { setMsg('authMsg', 'Не удалось загрузить настройки доступа: ' + (e.message || e), false); } } catch (e) {
if (Date.now() < authRestartUntil) {
setMsg('authMsg', 'Панель перезапускается, через пару секунд обновится...', null);
} else {
setMsg('authMsg', 'Не удалось загрузить настройки доступа: ' + (e.message || e), false);
}
}
} }
async function refreshStatus() { async function refreshStatus() {
try { try {
@@ -1355,6 +1380,7 @@ el('btnAuthSave').onclick = async () => {
if (password) payload.password = password; if (password) payload.password = password;
const r = await apiPost('/auth-config', payload); const r = await apiPost('/auth-config', payload);
el('authPassInput').value = ''; el('authPassInput').value = '';
authRestartUntil = Date.now() + 10000;
setMsg('authMsg', r.note || 'Сохранено. Войдите заново.', true); setMsg('authMsg', r.note || 'Сохранено. Войдите заново.', true);
} catch (e) { setMsg('authMsg', String(e.message || e), false); } } catch (e) { setMsg('authMsg', String(e.message || e), false); }
}; };