Terminal (PTY)¶
sbx.pty abre una terminal real dentro del sandbox: un shell de login
interactivo con su tamaño, sus colores y su control de trabajos, al que le
mandas teclas y del que recibes bytes.
Cuándo usarlo¶
- Programas interactivos que necesitan una terminal (
vim,htop, un REPL, un instalador que pregunta). - Dar a una persona una consola dentro del sandbox (por ejemplo, con
xterm.jsen el navegador). - Cuándo no: para ejecutar una orden y leer su salida, usa
comandos; es más simple y separa
stdoutdestderr.
Ejemplo rápido¶
from rayito import PtySize, Sandbox
with Sandbox.create() as sbx:
pty = sbx.pty.create(size=PtySize(cols=120, rows=40), timeout=None)
pty.send_input("echo hola\n")
for _, _, data in pty: # (1)!
if data and b"hola\r\n" in data:
break
pty.resize(PtySize(cols=80, rows=24))
pty.kill()
- Cada trozo llega como
(None, None, bytes): la salida cruda de la terminal, con secuencias de escape.
import asyncio
from rayito import AsyncSandbox, PtySize
async def main() -> None:
async with await AsyncSandbox.create() as sbx:
pty = await sbx.pty.create(size=PtySize(cols=120, rows=40), timeout=None)
await pty.send_input("echo hola\n")
async for _, _, data in pty:
if data and b"hola\r\n" in data:
break
await pty.resize(PtySize(cols=80, rows=24))
await pty.kill()
asyncio.run(main())
import { Sandbox } from "rayito";
await using sbx = await Sandbox.create();
const pty = await sbx.pty.create({ size: { cols: 120, rows: 40 }, timeoutMs: 0 });
await pty.sendInput("echo hola\n");
for await (const { pty: data } of pty) {
if (data !== undefined && new TextDecoder().decode(data).includes("hola\r\n")) break;
}
await pty.resize({ cols: 80, rows: 24 });
await pty.kill();
from rayito.e2b import PtySize, Sandbox
with Sandbox.create() as sbx:
chunks: list[bytes] = []
pty = sbx.pty.create(PtySize(rows=24, cols=80), on_data=chunks.append) # (1)!
sbx.pty.send_stdin(pty.pid, b"echo hola\n")
sbx.pty.resize(pty.pid, PtySize(rows=40, cols=120))
sbx.pty.kill(pty.pid)
- El orden de E2B,
PtySize(rows, cols), y sus firmas posicionales; devuelve el mismoPtyHandlenativo.
Paso a paso¶
pty.create()arranca el shell de login del usuario (<shell> -i -l, uid 1000) conTERM=xterm-256color. Devuelve unPtyHandle, que es unCommandHandlecuyos trozos son bytes de la terminal.send_input(data)escribe teclas (texto o bytes;"\x03"es Ctrl-C);send_stdin(data)es un alias con el nombre de E2B.- Lee la salida iterando el handle o con un callback
on_data(TypeScript:onData), que recibe cada trozo de bytes. resize(size)cambia filas y columnas: el programa recibeSIGWINCH.kill()termina la terminal;disconnect()la suelta sin matarla ypty.connect(pid)vuelve a engancharse más tarde, desde este u otro proceso, conon_data=,from_seq=ytimeout=(TypeScript:onData,fromSeq,timeoutMs).
Sin el handle, los mismos métodos van por pid en sbx.pty:
send_input(pid, data) (o send_stdin), resize(pid, size) y
kill(pid). El PtyHandle tiene además pid, exit_code, wait() y
close_stdin() como cualquier CommandHandle, y las PTY vivas aparecen en
commands.list() con kind="pty".
Para conectar una terminal web, reenvía los bytes de on_data al
navegador y lo que teclea el usuario a send_input.
Opciones de pty.create¶
| Python | TypeScript | Por defecto | Qué hace |
|---|---|---|---|
size |
size |
80×24 | PtySize(cols, rows) / { cols, rows } |
user |
user |
"user" |
usuario del shell |
cwd |
cwd |
el HOME |
directorio inicial |
envs |
envs |
— | variables de entorno del shell |
shell |
shell |
el de login | ruta absoluta de otro shell |
on_data |
onData |
— | callback con cada trozo de bytes |
timeout |
timeoutMs |
60 s / 60 000 ms | vida máxima de la terminal; None / 0 sin límite |
secrets |
secrets |
— | secretos en el entorno del shell (opcional, con coste) |
PtySize en el SDK nativo es PtySize(cols, rows); en el shim de E2B
mantiene el orden de E2B, PtySize(rows, cols).
Reconexión¶
Como los comandos, una PTY sobrevive a una pausa y a un corte del proxy: el
handle se reengancha solo (Pty.Connect) la próxima vez que lo lees, sin
perder salida. Leer una PTY de un sandbox suspendido no lo despierta.
Errores y solución de problemas¶
| Python | TypeScript | Cuándo | Qué hacer |
|---|---|---|---|
TimeoutException |
TimeoutError |
la terminal llegó a su timeout |
pasa timeout=None para sesiones largas |
RateLimitException |
RateLimitError |
demasiados procesos y PTYs vivos (Límites) | cierra terminales que no uses |
InvalidArgumentException |
InvalidArgumentError |
shell que no es una ruta absoluta, tamaño inválido |
corrige el argumento |
Diferencias con E2B¶
- El orden de
PtySizedel SDK nativo es(cols, rows); el shim de E2B conserva(rows, cols). send_stdinde E2B existe también en el SDK nativo como alias desend_input.
Ver también¶
- Comandos
- CLI:
rayito sandbox connect - Referencia: Python y TypeScript