Skip to main content

tick_daemon/
tick_daemon.rs

1use daemon_forge::ForgeDaemon;
2use std::fs::OpenOptions;
3use std::thread;
4use std::time::Duration;
5use std::env;
6use std::sync::Arc;
7use std::sync::atomic::{AtomicBool, Ordering};
8use signal_hook::consts::signal::*;
9use signal_hook::flag;
10
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12    // 1. Definir rutas
13    let pwd = env::current_dir().unwrap();
14    let log_path = pwd.join("ticker.log");
15    let err_path = pwd.join("ticker.err");
16    let pid_path = pwd.join("ticker.pid");
17
18    // 2. Abrir archivos de log (Append mode)
19    let stdout_file = OpenOptions::new()
20        .create(true)
21        .append(true)
22        .open(&log_path)
23        .expect("Couldn't open stdout");
24
25    let stderr_file = OpenOptions::new()
26        .create(true)
27        .append(true)
28        .open(&err_path)
29        .expect("Couldn't open stderr");
30
31    println!("Launching a simple ticker Daemon...");
32    println!("Logs will be written to: {:?}", log_path);
33
34    // 3. Configurar el Daemon
35    let daemon = ForgeDaemon::new()
36        .name("tick_daemon")
37        .pid_file(&pid_path)
38        .working_directory(&pwd)
39        .stdout(stdout_file)
40        .stderr(stderr_file)
41        // AQUÍ está el cambio principal: Pasamos la lógica como un closure
42        .privileged_action(move || {
43            
44            // --- INICIO CÓDIGO DEL DAEMON ---
45            
46            // A. Configurar manejo de señales para parada limpia (SIGTERM / SIGINT)
47            let term = Arc::new(AtomicBool::new(false));
48            flag::register(SIGTERM, Arc::clone(&term))?; // Systemd Stop
49            flag::register(SIGINT, Arc::clone(&term))?;  // Ctrl+C (Manual)
50
51            println!("[Ticker] Servicio iniciado. PID: {}", std::process::id());
52
53            let frases = [
54                "Estan vivos",
55                "I have no mouth",
56                "I must scream",
57                "Hello world",
58                "Adios mundo :0"
59            ];
60
61            let mut i = 0;
62
63            // B. Bucle principal que respeta la señal de parada
64            while !term.load(Ordering::Relaxed) {
65                let frase = frases[i % frases.len()];
66                
67                // C. Usamos println!: La librería ya redirigió esto al archivo .log
68                println!("[Ticker] Ping #{} - {}", i, frase);
69                
70                i += 1;
71                
72                // Dormir en intervalos cortos para revisar la señal de parada frecuentemente
73                thread::sleep(Duration::from_secs(3));
74            }
75
76            println!("[Ticker] Señal de parada recibida. Cerrando limpiamente.");
77            Ok(())
78        });
79
80    // 4. Arrancar usando la lógica refactorizada (Systemd o Fork)
81    // Nota: Usamos la función del módulo unix directamente
82    daemon_forge::ForgeDaemon::start(daemon)?;
83
84    Ok(())
85}