Skip to content

Instantly share code, notes, and snippets.

@iKunalChhabra
Created April 3, 2025 13:48
Show Gist options
  • Save iKunalChhabra/0b0e8fe17102c1aec420c3332c1b6ea8 to your computer and use it in GitHub Desktop.
Save iKunalChhabra/0b0e8fe17102c1aec420c3332c1b6ea8 to your computer and use it in GitHub Desktop.
FastAPI sever to execute unix commands and stream back the response via websockets
# main.py
import asyncio
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
app = FastAPI()
async def stream_shell_output(command: str, websocket: WebSocket) -> None:
"""
Execute a shell command and stream the output to the WebSocket client.
"""
process = await asyncio.create_subprocess_shell(
command,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
)
try:
assert process.stdout is not None
while True:
line = await process.stdout.readline()
if not line:
break
await websocket.send_text(line.decode().rstrip())
await process.wait()
await websocket.send_text(f"[EXIT CODE] {process.returncode}")
except asyncio.CancelledError:
process.kill()
await websocket.send_text("[CANCELLED]")
raise
finally:
await websocket.close()
@app.websocket("/ws/command")
async def websocket_command_handler(websocket: WebSocket):
await websocket.accept()
try:
command: str = await websocket.receive_text()
await stream_shell_output(command, websocket)
except WebSocketDisconnect:
print("WebSocket client disconnected")
except Exception as e:
await websocket.send_text(f"[ERROR] {str(e)}")
await websocket.close()
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", reload=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment