¿Cómo usar std.ChildProcess.init?

¿Cómo usar std.ChildProcess.init?

En Zig, la creación de procesos hijos se realiza a través de la estructura std.ChildProcess. Su método init permite configurar todos los parámetros necesarios: comando, argumentos, variables de entorno y directorio de trabajo. Una vez inicializado, el proceso se puede lanzar con spawn, esperar a que termine con wait y, si se desea, capturar su salida estándar.

Pasos básicos para usar std.ChildProcess.init

  • Importar el módulo estándar y la estructura ChildProcess.
  • Obtener un allocador, generalmente std.heap.page_allocator.
  • Llamar a ChildProcess.init pasando el comando, los argumentos y opcionalmente env y cwd.
  • Ejecutar el proceso con spawn.
  • Esperar su terminación con wait y leer el código de salida.
  • Liberar los recursos con destroy cuando ya no se necesiten.

Ejemplo sencillo: listar archivos con ls

const std = @import("std");                 // 1
const ChildProcess = std.ChildProcess;      // 2
const Allocator = std.mem.Allocator;        // 3

pub fn main() !void {                       // 4
    const gpa = std.heap.page_allocator;    // 5
    // Creamos un ChildProcess con el comando "ls" y los argumentos "-l" y "-a"
    var child = ChildProcess.init(          // 6
        gpa,                                // 7  Allocator
        "ls",                               // 8  comando a ejecutar
        &[_][]const u8{ "-l", "-a" },        // 9  argumentos del comando
        null,                               // 10  variables de entorno (none)
        null                                // 11  directorio de trabajo (current)
    );                                      // 12
    errdefer child.destroy();                // 13  asegurar limpieza en caso de error

    try child.spawn();                      // 14  lanzar el proceso
    const exit = try child.wait();          // 15  esperar a que termine

    std.debug.print(                        // 16  mostrar el código de salida
        "Child exited with status {}\n", .{exit.code}
    );                                      // 17
}                                            // 18

En el ejemplo anterior:

  • ChildProcess.init configura el proceso con el comando y los argumentos.
  • spawn lo ejecuta; si falla se genera un error que se propaga con try.
  • Tras wait, exit.code contiene el código de salida del hijo.
  • El bloque errdefer garantiza que destroy se ejecute si spawn o wait fallan.

Capturar la salida estándar

Si quieres leer la salida que genera el proceso, configura los stdout_behavior y stderr_behavior antes de spawn:

const std = @import("std");
const ChildProcess = std.ChildProcess;

pub fn main() !void {
    const gpa = std.heap.page_allocator;

    var child = ChildProcess.init(
        gpa,
        "ping",
        &[_][]const u8{ "-c", "2", "example.com" }, // ping dos veces
        null,
        null
    );

    // Capturamos stdout y stderr
    child.stdout_behavior = .capture;
    child.stderr_behavior = .capture;

    try child.spawn();

    // Esperamos la terminación
    const exit = try child.wait();

    // Convertimos la salida capturada en una cadena de bytes
    const stdout = try child.stdout.?.toOwnedSlice(gpa);
    defer gpa.free(stdout);

    const stderr = try child.stderr.?.toOwnedSlice(gpa);
    defer gpa.free(stderr);

    std.debug.print("Código de salida: {}\n", .{exit.code});
    std.debug.print("stdout: {s}\n", .{stdout});
    std.debug.print("stderr: {s}\n", .{stderr});
}

Detalles clave:

  • .capture indica que Zig debe asignar memoria y almacenar la salida.
  • Después de wait se accede a los buffers con child.stdout.?. y child.stderr.?..
  • Los buffers son de tipo []const u8; se convierten a slices manejados por el allocador para liberar correctamente.

Definir variables de entorno y directorio de trabajo

Para pasar variables de entorno personalizadas o cambiar el directorio de trabajo, simplemente provee los argumentos correspondientes a init:

const std = @import("std");
const ChildProcess = std.ChildProcess;

pub fn main() !void {
const gpa = std.heap.page_allocator;

// Variables de entorno: KEY=VALUE
const env_vars = &[_][]const u8{ "MYVAR=123", "ANOTHER=hello" };

// Directorio de trabajo (por ejemplo, /tmp)
const cwd = "/tmp";

var child = ChildProcess.init(
gpa,
"printenv",
&[_][]const u8{}, // sin argumentos
env_vars, // variables de entorno
cwd // directorio actual
);

child.stdout_behavior = .capture; // capturar salida

Comments

No comments yet. Why don’t you start the discussion?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *