Este manual está diseñado específicamente para administradores de sistemas Linux que desean utilizar Rust para automatización, herramientas de sistema y administración de infraestructura.

1. Instalación y Configuración en Linux

1.1. Instalación recomendada para sistemas

# Instalar Rust via rustup (recomendado)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile default

# Configurar entorno (añadir a ~/.bashrc o ~/.zshrc)
echo 'source $HOME/.cargo/env' >> ~/.bashrc
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Verificar instalación
rustc --version
cargo --version

1.2. Herramientas esenciales para sysadmins

# Instalar componentes adicionales
rustup component add rustfmt clippy rust-analysis rust-src

# Instalar herramientas útiles
cargo install exa      # ls moderno
cargo install bat      # cat con sintaxis coloreada
cargo install fd-find  # find alternativo
cargo install ripgrep  # grep alternativo
cargo install dust     # du alternativo
cargo install bottom   # top alternativo

1.3. Configuración para entornos de producción

# Configurar variables de entorno (en ~/.bashrc o ~/.profile)
export RUST_BACKTRACE=full       # Para debugging completo
export CARGO_HOME="$HOME/.cargo" # Localización de cargo
export RUSTUP_HOME="$HOME/.rustup" # Localización de rustup

# Para builds optimizados
export RUSTFLAGS="-C target-cpu=native -C opt-level=3"

2. Fundamentos de Rust para Sysadmins

2.1. Manejo de archivos y directorios

Operaciones básicas con archivos
use std::fs;
use std::io::{self, Write};
use std::path::Path;

fn main() -> io::Result<()> {
    // Crear directorio
    fs::create_dir_all("/tmp/rust_sysadmin")?;
    
    // Escribir archivo
    let mut file = fs::File::create("/tmp/rust_sysadmin/test.txt")?;
    file.write_all(b"Hola, administrador de sistemas!")?;
    
    // Leer archivo
    let content = fs::read_to_string("/tmp/rust_sysadmin/test.txt")?;
    println!("Contenido: {}", content);
    
    // Verificar existencia
    if Path::new("/tmp/rust_sysadmin/test.txt").exists() {
        println!("El archivo existe");
    }
    
    // Copiar archivo
    fs::copy("/tmp/rust_sysadmin/test.txt", "/tmp/rust_sysadmin/test_copy.txt")?;
    
    // Eliminar archivo
    fs::remove_file("/tmp/rust_sysadmin/test_copy.txt")?;
    
    // Listar directorio
    for entry in fs::read_dir("/tmp/rust_sysadmin")? {
        let entry = entry?;
        println!("{:?}", entry.path());
    }
    
    Ok(())
}

2.2. Procesamiento de texto y logs

Análisis de logs
use std::fs::File;
use std::io::{BufRead, BufReader};

fn analyze_logs(file_path: &str) -> std::io::Result<()> {
    let file = File::open(file_path)?;
    let reader = BufReader::new(file);
    
    let mut error_count = 0;
    let mut warning_count = 0;
    let mut info_count = 0;
    
    for line in reader.lines() {
        let line = line?;
        
        if line.contains("ERROR") {
            error_count += 1;
            println!("Error encontrado: {}", line);
        } else if line.contains("WARNING") {
            warning_count += 1;
        } else if line.contains("INFO") {
            info_count += 1;
        }
    }
    
    println!("Resumen del análisis:");
    println!("- Errores: {}", error_count);
    println!("- Advertencias: {}", warning_count);
    println!("- Información: {}", info_count);
    
    Ok(())
}

fn main() {
    if let Err(e) = analyze_logs("/var/log/syslog") {
        eprintln!("Error al analizar logs: {}", e);
    }
}

3. Automatización de Tareas del Sistema

3.1. Ejecución de comandos del sistema

Ejecutar y controlar procesos
use std::process::{Command, Stdio};
use std::io::{self, Write};

fn run_system_command() -> io::Result<()> {
    // Comando simple
    let output = Command::new("ls")
        .arg("-lh")
        .arg("/var/log")
        .output()?;
    
    println!("Salida:\n{}", String::from_utf8_lossy(&output.stdout));
    
    // Comando con pipes (similar a shell)
    let mut child = Command::new("grep")
        .arg("error")
        .arg("/var/log/syslog")
        .stdout(Stdio::piped())
        .spawn()?;
    
    let grep_output = child.wait_with_output()?;
    io::stdout().write_all(&grep_output.stdout)?;
    
    // Comando con entorno personalizado
    Command::new("bash")
        .arg("-c")
        .arg("echo $MY_VAR")
        .env("MY_VAR", "valor_personalizado")
        .status()?;
    
    Ok(())
}

fn main() {
    if let Err(e) = run_system_command() {
        eprintln!("Error al ejecutar comando: {}", e);
    }
}

3.2. Monitoreo del sistema

Monitor de recursos del sistema
use std::process::Command;
use std::thread;
use std::time::Duration;

fn monitor_system(interval_secs: u64) {
    loop {
        // Limpiar pantalla (similar a 'clear')
        print!("\x1B[2J\x1B[1;1H");
        
        // Obtener uso de CPU
        let cpu = Command::new("sh")
            .arg("-c")
            .arg("top -bn1 | grep 'Cpu(s)' | sed 's/.*, *\\([0-9.]*\\)%* id.*/\\1/' | awk '{print 100 - $1}'")
            .output()
            .expect("Error al obtener uso de CPU");
        
        // Obtener memoria libre
        let memory = Command::new("free")
            .arg("-m")
            .output()
            .expect("Error al obtener memoria libre");
        
        // Obtener espacio en disco
        let disk = Command::new("df")
            .arg("-h")
            .arg("/")
            .output()
            .expect("Error al obtener espacio en disco");
        
        println!("=== Monitor del Sistema ===");
        println!("Uso de CPU: {}%", String::from_utf8_lossy(&cpu.stdout).trim());
        println!("Memoria:\n{}", String::from_utf8_lossy(&memory.stdout));
        println!("Disco:\n{}", String::from_utf8_lossy(&disk.stdout));
        
        thread::sleep(Duration::from_secs(interval_secs));
    }
}

fn main() {
    monitor_system(2);
}

4. Herramientas de Red

4.1. Escaneo de puertos

Escáner de puertos básico
use std::net::{TcpStream, SocketAddr};
use std::time::Duration;
use std::thread;

fn port_scan(target: &str, start_port: u16, end_port: u16, timeout_ms: u64) {
    println!("Escaneando {} (puertos {}-{})", target, start_port, end_port);
    
    for port in start_port..=end_port {
        let target = target.to_string();
        thread::spawn(move || {
            let socket_addr = format!("{}:{}", target, port);
            if let Ok(addr) = socket_addr.parse::() {
                if TcpStream::connect_timeout(&addr, Duration::from_millis(timeout_ms)).is_ok() {
                    println!("Puerto {} abierto", port);
                }
            }
        });
    }
    
    // Esperar a que terminen los hilos
    thread::sleep(Duration::from_secs(2));
}

fn main() {
    port_scan("127.0.0.1", 80, 100, 200);
}

4.2. Cliente HTTP para APIs REST

Interacción con APIs web
use reqwest::blocking::Client;
use serde_json::Value;
use std::collections::HashMap;

fn check_web_service(url: &str) -> Result<(), reqwest::Error> {
    let client = Client::new();
    
    // GET request
    let response = client.get(url).send()?;
    println!("Status: {}", response.status());
    println!("Headers:\n{:#?}", response.headers());
    
    // POST request con JSON
    let mut map = HashMap::new();
    map.insert("service", "healthcheck");
    map.insert("status", "ok");
    
    let response = client.post("https://httpbin.org/post")
        .json(&map)
        .send()?;
    
    let json: Value = response.json()?;
    println!("Respuesta JSON:\n{}", serde_json::to_string_pretty(&json)?);
    
    Ok(())
}

fn main() {
    if let Err(e) = check_web_service("https://httpbin.org/get") {
        eprintln!("Error al verificar servicio web: {}", e);
    }
}

5. Seguridad del Sistema

5.1. Verificación de integridad de archivos

Checksum de archivos
use std::fs::File;
use std::io::{Read};
use sha2::{Sha256, Digest};
use std::path::Path;

fn calculate_sha256(file_path: &str) -> std::io::Result {
    let mut file = File::open(file_path)?;
    let mut hasher = Sha256::new();
    let mut buffer = [0; 1024];
    
    loop {
        let bytes_read = file.read(&mut buffer)?;
        if bytes_read == 0 {
            break;
        }
        hasher.update(&buffer[..bytes_read]);
    }
    
    Ok(format!("{:x}", hasher.finalize()))
}

fn monitor_file_changes(file_path: &str) -> std::io::Result<()> {
    let original_hash = calculate_sha256(file_path)?;
    println!("Hash original de {}: {}", file_path, original_hash);
    
    // En producción, aquí iría un loop con sleep para monitoreo continuo
    let current_hash = calculate_sha256(file_path)?;
    
    if original_hash != current_hash {
        println!("ALERTA: El archivo {} ha sido modificado!", file_path);
        println!("Nuevo hash: {}", current_hash);
    } else {
        println!("El archivo no ha sido modificado");
    }
    
    Ok(())
}

fn main() {
    if let Err(e) = monitor_file_changes("/etc/passwd") {
        eprintln!("Error: {}", e);
    }
}

5.2. Gestión de usuarios y permisos

Verificación de permisos
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use std::fs;

fn check_file_permissions(file_path: &str) -> std::io::Result<()> {
    let metadata = fs::metadata(file_path)?;
    let permissions = metadata.permissions();
    let mode = permissions.mode();
    
    println!("Permisos de {}: {:o}", file_path, mode & 0o777);
    
    // Verificar permisos inseguros
    if mode & 0o777 == 0o777 {
        println!("ADVERTENCIA: Permisos demasiado abiertos (777) en {}", file_path);
    }
    
    // Verificar propiedad
    if metadata.uid() == 0 {
        println!("ADVERTENCIA: Archivo propiedad de root: {}", file_path);
    }
    
    Ok(())
}

fn main() {
    let critical_files = [
        "/etc/passwd",
        "/etc/shadow",
        "/etc/sudoers",
        "/etc/ssh/sshd_config"
    ];
    
    for file in &critical_files {
        if Path::new(file).exists() {
            if let Err(e) = check_file_permissions(file) {
                eprintln!("Error al verificar {}: {}", file, e);
            }
        }
    }
}

6. Creación de Herramientas CLI

6.1. Argumentos de línea de comandos

CLI profesional con Clap
use clap::{Arg, App, SubCommand};

fn main() {
    let matches = App::new("SysAdmin Tool")
        .version("1.0")
        .author("Admin ")
        .about("Herramienta de administración de sistemas")
        .subcommand(SubCommand::with_name("scan")
            .about("Escanea puertos en un host")
            .arg(Arg::with_name("host")
                .help("Host a escanear")
                .required(true)
                .index(1))
            .arg(Arg::with_name("start_port")
                .short("s")
                .long("start")
                .help("Puerto inicial")
                .default_value("1"))
            .arg(Arg::with_name("end_port")
                .short("e")
                .long("end")
                .help("Puerto final")
                .default_value("1024")))
        .subcommand(SubCommand::with_name("monitor")
            .about("Monitor del sistema")
            .arg(Arg::with_name("interval")
                .short("i")
                .long("interval")
                .help("Intervalo en segundos")
                .default_value("5")))
        .get_matches();
    
    match matches.subcommand() {
        ("scan", Some(scan_matches)) => {
            let host = scan_matches.value_of("host").unwrap();
            let start_port: u16 = scan_matches.value_of("start_port").unwrap().parse().unwrap();
            let end_port: u16 = scan_matches.value_of("end_port").unwrap().parse().unwrap();
            
            println!("Escaneando {} (puertos {}-{})", host, start_port, end_port);
            // Aquí iría la lógica de escaneo
        },
        ("monitor", Some(monitor_matches)) => {
            let interval: u64 = monitor_matches.value_of("interval").unwrap().parse().unwrap();
            println!("Iniciando monitor con intervalo de {} segundos", interval);
            // Aquí iría la lógica de monitoreo
        },
        _ => {
            println!("Use --help para ver las opciones");
        }
    }
}

6.2. Herramienta de backup

Script de backup con compresión
use std::fs;
use std::path::Path;
use std::process::Command;
use chrono::Local;
use flate2::write::GzEncoder;
use flate2::Compression;
use std::fs::File;
use std::io::Write;

fn create_backup(source: &str, dest_dir: &str) -> std::io::Result<()> {
    // Crear directorio de destino si no existe
    fs::create_dir_all(dest_dir)?;
    
    // Nombre del archivo de backup con timestamp
    let timestamp = Local::now().format("%Y%m%d_%H%M%S");
    let backup_name = format!("{}/backup_{}.tar.gz", dest_dir, timestamp);
    
    // Crear archivo comprimido
    let tar_gz = File::create(&backup_name)?;
    let enc = GzEncoder::new(tar_gz, Compression::default());
    let mut tar = tar::Builder::new(enc);
    
    // Añadir directorio al tar
    tar.append_dir_all("backup", source)?;
    
    println!("Backup creado exitosamente: {}", backup_name);
    
    // Verificar integridad del backup
    let output = Command::new("gzip")
        .arg("-t")
        .arg(&backup_name)
        .output()?;
    
    if output.status.success() {
        println!("Verificación de integridad exitosa");
    } else {
        eprintln!("Error: El archivo de backup está corrupto");
        fs::remove_file(backup_name)?;
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidData,
            "Backup corrupto"
        ));
    }
    
    Ok(())
}

fn main() {
    let args: Vec = std::env::args().collect();
    
    if args.len() != 3 {
        eprintln!("Uso: {}  ", args[0]);
        std::process::exit(1);
    }
    
    if let Err(e) = create_backup(&args[1], &args[2]) {
        eprintln!("Error al crear backup: {}", e);
        std::process::exit(1);
    }
}

7. Integración con Systemd

7.1. Creación de un servicio systemd

Demonio Rust como servicio systemd
use std::fs;
use std::io::Write;
use std::thread;
use std::time::Duration;

fn daemon_work() {
    loop {
        // Simular trabajo del demonio
        let log_entry = format!("[{}] Demonio activo\n", chrono::Local::now());
        
        // Escribir en log (en producción usaría syslog)
        if let Ok(mut file) = fs::OpenOptions::new()
            .append(true)
            .create(true)
            .open("/var/log/rust_daemon.log") 
        {
            let _ = file.write_all(log_entry.as_bytes());
        }
        
        thread::sleep(Duration::from_secs(60));
    }
}

fn main() {
    // Configurar comportamiento ante señales
    ctrlc::set_handler(move || {
        println!("Recibida señal de terminación");
        // Limpieza antes de salir
        std::process::exit(0);
    }).expect("Error al configurar manejador de señales");
    
    println!("Iniciando demonio...");
    daemon_work();
}

Archivo de servicio systemd (/etc/systemd/system/rust-daemon.service):

[Unit]
Description=Rust System Daemon
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/rust-daemon
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Comandos para administrar el servicio:

# Recargar systemd
sudo systemctl daemon-reload

# Habilitar e iniciar el servicio
sudo systemctl enable rust-daemon
sudo systemctl start rust-daemon

# Verificar estado
sudo systemctl status rust-daemon

# Ver logs
journalctl -u rust-daemon -f

8. Proyectos Recomendados para Sysadmins

8.1. Dependencias útiles

Crate Propósito
clap Parseo de argumentos CLI
sysinfo Información del sistema
libc LLamadas al sistema
nix API Unix avanzada
users Gestión de usuarios
shadow-rs Información de build
indicatif Barras de progreso
serde_json Manejo de JSON
reqwest Cliente HTTP
tar, flate2 Compresión

8.2. Ideas para proyectos

9. Buenas Prácticas para Sysadmins

9.1. Consejos para código de sistemas

9.2. Optimización para sistemas

10. Recursos Adicionales

10.1. Libros y documentación

10.2. Comunidad

Consejo profesional: Empieza por reescribir tus scripts Bash existentes en Rust para familiarizarte con el lenguaje. Prioriza herramientas que necesiten mayor seguridad o rendimiento.

Conclusión

Rust es una excelente opción para administradores de sistemas Linux que necesitan:

Con su creciente adopción en infraestructura (Firecracker, Docker, Kubernetes), aprender Rust proporciona una valiosa habilidad para cualquier administrador de sistemas moderno.