Como Obter Informações do Sistema em Zig

Introdução

Obter informações sobre o sistema é útil para logs, diagnóstico, ajuste de performance e decisões em tempo de execução (como número de threads). Zig permite acessar informações do OS através da biblioteca padrão e de chamadas POSIX.

Nesta receita, você aprenderá a obter dados sobre o sistema operacional, hardware e ambiente.

Pré-requisitos

Número de CPUs

const std = @import("std");

pub fn main() !void {
    // Obter número de CPUs disponíveis
    const cpus = try std.Thread.getCpuCount();
    std.debug.print("CPUs disponíveis: {d}\n", .{cpus});
}

Informações do Sistema Operacional

const std = @import("std");

pub fn main() !void {
    // Informações sobre o target (compilação)
    const target = @import("builtin").target;

    std.debug.print("=== Informações do Target ===\n", .{});
    std.debug.print("OS: {s}\n", .{@tagName(target.os.tag)});
    std.debug.print("Arch: {s}\n", .{@tagName(target.cpu.arch)});
    std.debug.print("Endian: {s}\n", .{@tagName(target.cpu.arch.endian())});

    // ABI
    std.debug.print("ABI: {s}\n", .{@tagName(target.abi)});

    // Número de CPUs
    const cpus = try std.Thread.getCpuCount();
    std.debug.print("\n=== Hardware ===\n", .{});
    std.debug.print("CPUs: {d}\n", .{cpus});

    // Tamanho da página de memória
    const page_size = std.mem.page_size;
    std.debug.print("Tamanho da página: {d} bytes ({d} KB)\n", .{ page_size, page_size / 1024 });
}

Hostname e Variáveis de Ambiente

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    std.debug.print("=== Informações do Ambiente ===\n", .{});

    // Hostname (via variável de ambiente ou arquivo)
    if (std.posix.getenv("HOSTNAME")) |hostname| {
        std.debug.print("Hostname: {s}\n", .{hostname});
    } else {
        // Tentar ler /etc/hostname
        if (std.fs.cwd().readFileAlloc(allocator, "/etc/hostname", 256)) |hostname| {
            defer allocator.free(hostname);
            const limpo = std.mem.trim(u8, hostname, " \t\n\r");
            std.debug.print("Hostname: {s}\n", .{limpo});
        } else |_| {
            std.debug.print("Hostname: (indisponível)\n", .{});
        }
    }

    // Usuário atual
    if (std.posix.getenv("USER")) |user| {
        std.debug.print("Usuário: {s}\n", .{user});
    }

    // Diretório home
    if (std.posix.getenv("HOME")) |home| {
        std.debug.print("Home: {s}\n", .{home});
    }

    // Shell
    if (std.posix.getenv("SHELL")) |shell| {
        std.debug.print("Shell: {s}\n", .{shell});
    }

    // Diretório de trabalho atual
    const cwd = try std.fs.cwd().realpathAlloc(allocator, ".");
    defer allocator.free(cwd);
    std.debug.print("CWD: {s}\n", .{cwd});
}

PID do Processo

const std = @import("std");

pub fn main() !void {
    const pid = std.os.linux.getpid();
    std.debug.print("PID do processo: {d}\n", .{pid});

    const ppid = std.os.linux.getppid();
    std.debug.print("PID do pai: {d}\n", .{ppid});

    const uid = std.os.linux.getuid();
    std.debug.print("UID: {d}\n", .{uid});

    const gid = std.os.linux.getgid();
    std.debug.print("GID: {d}\n", .{gid});
}

Relatório Completo do Sistema

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const target = @import("builtin").target;

    std.debug.print("╔══════════════════════════════════╗\n", .{});
    std.debug.print("║    Relatório do Sistema (Zig)    ║\n", .{});
    std.debug.print("╚══════════════════════════════════╝\n\n", .{});

    // Compilação
    std.debug.print("[Compilação]\n", .{});
    std.debug.print("  Zig version: {s}\n", .{@import("builtin").zig_version_string});
    std.debug.print("  Target OS: {s}\n", .{@tagName(target.os.tag)});
    std.debug.print("  Target CPU: {s}\n", .{@tagName(target.cpu.arch)});
    std.debug.print("  Modo: {s}\n", .{@tagName(@import("builtin").mode)});

    // Hardware
    std.debug.print("\n[Hardware]\n", .{});
    const cpus = try std.Thread.getCpuCount();
    std.debug.print("  CPUs: {d}\n", .{cpus});
    std.debug.print("  Página de memória: {d} bytes\n", .{std.mem.page_size});

    // Ambiente
    std.debug.print("\n[Ambiente]\n", .{});
    const variaveis = [_][]const u8{ "USER", "HOME", "SHELL", "LANG", "TERM" };
    for (&variaveis) |nome| {
        if (std.posix.getenv(nome)) |valor| {
            std.debug.print("  {s}: {s}\n", .{ nome, valor });
        }
    }

    // CWD
    if (std.fs.cwd().realpathAlloc(allocator, ".")) |cwd| {
        defer allocator.free(cwd);
        std.debug.print("  CWD: {s}\n", .{cwd});
    } else |_| {}

    // Tempo
    std.debug.print("\n[Tempo]\n", .{});
    std.debug.print("  Timestamp: {d}\n", .{std.time.timestamp()});
}

Dicas e Boas Práticas

  1. Use @import("builtin"): Para informações de tempo de compilação (OS, CPU, modo de otimização).

  2. Thread.getCpuCount(): Útil para dimensionar thread pools.

  3. Variáveis de ambiente como fallback: Nem toda informação está disponível em todos os SOs.

  4. Linux-specific: Funções como std.os.linux.* só funcionam em Linux. Use condicionais de compilação para portabilidade.

Receitas Relacionadas

Tutoriais Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.