Ejecutando comandos en Rust: cómo capturar la salida en 2025

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

De Python a Rust: la evolución de la ejecución de comandos

\n\n

Si alguna vez se ha preguntado «How do I invoke a system command and capture its output?» en Stack Overflow, sabrá que es una de las preguntas más populares y vitales para cualquier desarrollador. En el mundo de Python, la respuesta es simple: subprocess.check_output(). Pero, ¿qué hacer si ha migrado a Rust y desea no solo ejecutar un comando, sino hacerlo de manera elegante, segura y con el máximo rendimiento?

\n\n

Rust no es solo «otro lenguaje». Es un sistema donde cada byte está bajo control y los errores de ejecución de comandos no provocan el colapso de toda la aplicación. En 2025, cuando la seguridad y la velocidad se han convertido en el estándar de facto, saber trabajar correctamente con subprocesos en Rust es una habilidad imprescindible. Analicemos las mejores prácticas que transformarán la ejecución de comandos del sistema de una rutina en un arte.

\n\n

std::process::Command: su navaja suiza

\n\n

El corazón de la ejecución de comandos en Rust es el módulo std::process::Command. Proporciona todo lo necesario para ejecutar programas externos, capturar su salida y manejar errores. A diferencia de Python, donde subprocess oculta muchos detalles, Rust le brinda control total.

\n\n

Ejemplo básico: captura de stdout

\n\n

Empecemos con lo clásico: ejecutemos el comando echo "Hello, Rust!" y capturemos su salida:

\n\n
use std::process::Command;\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n    let output = Command::new("echo")\n        .arg("Hello, Rust!")\n        .output()?;\n\n    let stdout = String::from_utf8(output.stdout)?;\n    println!("Salida del comando: {}", stdout);\n\n    Ok(())\n}\n
\n\n

¿Qué es importante aquí? Usamos .output(), que devuelve una estructura Output. Contiene tres campos: stdout, stderr y status. Observe el ?: es el operador de propagación de errores, que nos evita los engorrosos bloques match. Rust nos obliga a manejar explícitamente posibles fallos: el comando puede no existir, no tener permisos de acceso o simplemente terminar con un error.

\n\n

Manejo de stderr y código de retorno

\n\n

En escenarios reales, no solo necesita stdout, sino también stderr. Imagine que ejecuta ls /nonexistent, un comando que seguramente generará un error:

\n\n
use std::process::Command;\n\nfn main() {\n    let output = Command::new("ls")\n        .arg("/nonexistent")\n        .output()\n        .expect("No se pudo ejecutar el comando");\n\n    if output.status.success() {\n        let stdout = String::from_utf8_lossy(&output.stdout);\n        println!("Éxito: {}", stdout);\n    } else {\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        eprintln!("Error (código {}): {}", output.status.code().unwrap_or(-1), stderr);\n    }\n}\n
\n\n

Aquí usamos String::from_utf8_lossy(): una forma segura de convertir bytes a cadena que reemplaza los caracteres UTF-8 no válidos con �. Esto es crítico si la salida del comando contiene datos binarios o utiliza una codificación impredecible.

\n\n

Técnicas avanzadas: asincronía y tuberías

\n\n

En 2025, la ejecución síncrona de comandos es una mala práctica. Las aplicaciones modernas requieren asincronía, especialmente si trabaja con servidores web o procesa múltiples comandos simultáneamente. Rust, con su ecosistema Tokio, ofrece una solución elegante.

\n\n

Captura asíncrona de salida con Tokio

\n\n

Agreguemos la dependencia en Cargo.toml:

\n\n
[dependencies]\ntokio = { version = "1", features = ["full"] }\n
\n\n

Ahora ejecutemos el comando de forma asíncrona:

\n\n
use tokio::process::Command;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let output = Command::new("sleep")\n        .arg("2")\n        .output()\n                

Blogs

Book Recommendations