SANDBOXBACKEND2 / app.py
theguywhosucks's picture
Update app.py
daa18cc verified
Raw
History Blame Contribute Delete
4.62 kB
import os
import uuid
import subprocess
import resource
import multiprocessing
import signal
import time
import shutil
import gradio as gr
import threading
# -------------------------
# Sandbox storage
# -------------------------
sandboxes = {}
SANDBOX_TTL = 2*3600 # 2 hours
# -------------------------
# Worker to run bare-metal process
# -------------------------
def sandbox_worker(code: str, sandbox_id: str):
user_dir = f"/tmp/sandbox_{sandbox_id}"
os.makedirs(user_dir, exist_ok=True)
os.chdir(user_dir)
# Resource limits
resource.setrlimit(resource.RLIMIT_AS, (4*1024**3, 4*1024**3)) # 4GB RAM
resource.setrlimit(resource.RLIMIT_CPU, (SANDBOX_TTL, SANDBOX_TTL)) # 2h CPU
# Save code as a script
code_file = os.path.join(user_dir, "user_code.sh")
with open(code_file, "w") as f:
f.write(code)
os.chmod(code_file, 0o755) # make executable
try:
result = subprocess.run(
["/bin/bash", code_file],
capture_output=True,
text=True,
timeout=SANDBOX_TTL
)
# Save logs
with open(os.path.join(user_dir, "stdout.log"), "w") as f:
f.write(result.stdout)
with open(os.path.join(user_dir, "stderr.log"), "w") as f:
f.write(result.stderr)
except subprocess.TimeoutExpired:
with open(os.path.join(user_dir, "stderr.log"), "w") as f:
f.write("Execution timed out (2h limit).")
# -------------------------
# Auto-cleanup thread
# -------------------------
def cleanup_sandboxes():
while True:
now = time.time()
for sid, info in list(sandboxes.items()):
if now - info["start_time"] > SANDBOX_TTL:
try:
os.kill(info["pid"], signal.SIGKILL)
except:
pass
folder = f"/tmp/sandbox_{sid}"
if os.path.exists(folder):
shutil.rmtree(folder)
del sandboxes[sid]
time.sleep(60)
threading.Thread(target=cleanup_sandboxes, daemon=True).start()
# -------------------------
# Gradio API functions
# -------------------------
def launch_sandbox(code):
sandbox_id = str(uuid.uuid4())[:8]
p = multiprocessing.Process(target=sandbox_worker, args=(code, sandbox_id))
p.start()
sandboxes[sandbox_id] = {"pid": p.pid, "start_time": time.time()}
return f"Sandbox launched! ID: {sandbox_id}", sandbox_id
def fetch_logs(sandbox_id):
user_dir = f"/tmp/sandbox_{sandbox_id}"
if not os.path.exists(user_dir):
return "Sandbox not found."
stdout = open(os.path.join(user_dir, "stdout.log")).read() if os.path.exists(os.path.join(user_dir, "stdout.log")) else ""
stderr = open(os.path.join(user_dir, "stderr.log")).read() if os.path.exists(os.path.join(user_dir, "stderr.log")) else ""
return f"STDOUT:\n{stdout}\n\nSTDERR:\n{stderr}"
def kill_sandbox(sandbox_id):
if sandbox_id not in sandboxes:
return "Sandbox not found."
try:
os.kill(sandboxes[sandbox_id]["pid"], signal.SIGKILL)
folder = f"/tmp/sandbox_{sandbox_id}"
if os.path.exists(folder):
shutil.rmtree(folder)
del sandboxes[sandbox_id]
return f"Sandbox {sandbox_id} killed."
except Exception as e:
return f"Error: {e}"
def status_sandbox(sandbox_id):
if sandbox_id not in sandboxes:
return "Sandbox not found."
elapsed = int(time.time() - sandboxes[sandbox_id]["start_time"])
return f"Running for {elapsed} seconds"
# -------------------------
# Gradio UI
# -------------------------
with gr.Blocks() as demo:
gr.Markdown("# 🛡 Bare-Metal Sandbox")
code_input = gr.Textbox(label="Shell Script / Commands", lines=15, placeholder="#!/bin/bash\nls -la")
launch_btn = gr.Button("Launch Sandbox")
sandbox_id_output = gr.Textbox(label="Sandbox ID")
logs_btn = gr.Button("Fetch Logs")
logs_output = gr.Textbox(label="Logs", lines=10)
kill_btn = gr.Button("Kill Sandbox")
kill_output = gr.Textbox(label="Kill Status")
status_btn = gr.Button("Check Status")
status_output = gr.Textbox(label="Sandbox Status")
sandbox_state = gr.State(value=None)
launch_btn.click(
launch_sandbox,
inputs=code_input,
outputs=[sandbox_id_output, sandbox_state]
)
logs_btn.click(fetch_logs, inputs=sandbox_state, outputs=logs_output)
kill_btn.click(kill_sandbox, inputs=sandbox_state, outputs=kill_output)
status_btn.click(status_sandbox, inputs=sandbox_state, outputs=status_output)
demo.launch()