aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs35
1 files changed, 18 insertions, 17 deletions
diff --git a/src/main.rs b/src/main.rs
index e0545e6..12a08b6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,6 +8,7 @@ use std::path::Path;
8use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; 8use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
9use std::sync::mpsc::channel; 9use std::sync::mpsc::channel;
10use glob::glob; 10use glob::glob;
11use anyhow::{Result, Context};
11 12
12#[derive(Parser)] 13#[derive(Parser)]
13#[command(name = "demon")] 14#[command(name = "demon")]
@@ -114,11 +115,11 @@ fn main() {
114 } 115 }
115} 116}
116 117
117fn run_command(command: Commands) -> Result<(), Box<dyn std::error::Error>> { 118fn run_command(command: Commands) -> Result<()> {
118 match command { 119 match command {
119 Commands::Run(args) => { 120 Commands::Run(args) => {
120 if args.command.is_empty() { 121 if args.command.is_empty() {
121 return Err("Command cannot be empty".into()); 122 return Err(anyhow::anyhow!("Command cannot be empty"));
122 } 123 }
123 run_daemon(&args.id, &args.command) 124 run_daemon(&args.id, &args.command)
124 } 125 }
@@ -147,14 +148,14 @@ fn run_command(command: Commands) -> Result<(), Box<dyn std::error::Error>> {
147 } 148 }
148} 149}
149 150
150fn run_daemon(id: &str, command: &[String]) -> Result<(), Box<dyn std::error::Error>> { 151fn run_daemon(id: &str, command: &[String]) -> Result<()> {
151 let pid_file = format!("{}.pid", id); 152 let pid_file = format!("{}.pid", id);
152 let stdout_file = format!("{}.stdout", id); 153 let stdout_file = format!("{}.stdout", id);
153 let stderr_file = format!("{}.stderr", id); 154 let stderr_file = format!("{}.stderr", id);
154 155
155 // Check if process is already running 156 // Check if process is already running
156 if is_process_running(&pid_file)? { 157 if is_process_running(&pid_file)? {
157 return Err(format!("Process '{}' is already running", id).into()); 158 return Err(anyhow::anyhow!("Process '{}' is already running", id));
158 } 159 }
159 160
160 tracing::info!("Starting daemon '{}' with command: {:?}", id, command); 161 tracing::info!("Starting daemon '{}' with command: {:?}", id, command);
@@ -177,7 +178,7 @@ fn run_daemon(id: &str, command: &[String]) -> Result<(), Box<dyn std::error::Er
177 .stderr(Stdio::from(stderr_redirect)) 178 .stderr(Stdio::from(stderr_redirect))
178 .stdin(Stdio::null()) 179 .stdin(Stdio::null())
179 .spawn() 180 .spawn()
180 .map_err(|e| format!("Failed to start process '{}': {}", program, e))?; 181 .with_context(|| format!("Failed to start process '{}' with args {:?}", program, args))?;
181 182
182 // Write PID to file 183 // Write PID to file
183 let mut pid_file_handle = File::create(&pid_file)?; 184 let mut pid_file_handle = File::create(&pid_file)?;
@@ -191,7 +192,7 @@ fn run_daemon(id: &str, command: &[String]) -> Result<(), Box<dyn std::error::Er
191 Ok(()) 192 Ok(())
192} 193}
193 194
194fn is_process_running(pid_file: &str) -> Result<bool, Box<dyn std::error::Error>> { 195fn is_process_running(pid_file: &str) -> Result<bool> {
195 // Try to read the PID file 196 // Try to read the PID file
196 let mut file = match File::open(pid_file) { 197 let mut file = match File::open(pid_file) {
197 Ok(f) => f, 198 Ok(f) => f,
@@ -214,7 +215,7 @@ fn is_process_running(pid_file: &str) -> Result<bool, Box<dyn std::error::Error>
214 Ok(output.status.success()) 215 Ok(output.status.success())
215} 216}
216 217
217fn stop_daemon(id: &str, timeout: u64) -> Result<(), Box<dyn std::error::Error>> { 218fn stop_daemon(id: &str, timeout: u64) -> Result<()> {
218 let pid_file = format!("{}.pid", id); 219 let pid_file = format!("{}.pid", id);
219 220
220 // Check if PID file exists 221 // Check if PID file exists
@@ -255,7 +256,7 @@ fn stop_daemon(id: &str, timeout: u64) -> Result<(), Box<dyn std::error::Error>>
255 .output()?; 256 .output()?;
256 257
257 if !output.status.success() { 258 if !output.status.success() {
258 return Err(format!("Failed to send SIGTERM to PID {}", pid).into()); 259 return Err(anyhow::anyhow!("Failed to send SIGTERM to PID {}", pid));
259 } 260 }
260 261
261 // Wait for the process to terminate 262 // Wait for the process to terminate
@@ -280,14 +281,14 @@ fn stop_daemon(id: &str, timeout: u64) -> Result<(), Box<dyn std::error::Error>>
280 .output()?; 281 .output()?;
281 282
282 if !output.status.success() { 283 if !output.status.success() {
283 return Err(format!("Failed to send SIGKILL to PID {}", pid).into()); 284 return Err(anyhow::anyhow!("Failed to send SIGKILL to PID {}", pid));
284 } 285 }
285 286
286 // Wait a bit more for SIGKILL to take effect 287 // Wait a bit more for SIGKILL to take effect
287 thread::sleep(Duration::from_secs(1)); 288 thread::sleep(Duration::from_secs(1));
288 289
289 if is_process_running_by_pid(pid) { 290 if is_process_running_by_pid(pid) {
290 return Err(format!("Process {} is still running after SIGKILL", pid).into()); 291 return Err(anyhow::anyhow!("Process {} is still running after SIGKILL", pid));
291 } 292 }
292 293
293 println!("Process '{}' (PID: {}) terminated forcefully", id, pid); 294 println!("Process '{}' (PID: {}) terminated forcefully", id, pid);
@@ -307,7 +308,7 @@ fn is_process_running_by_pid(pid: u32) -> bool {
307 } 308 }
308} 309}
309 310
310fn cat_logs(id: &str, show_stdout: bool, show_stderr: bool) -> Result<(), Box<dyn std::error::Error>> { 311fn cat_logs(id: &str, show_stdout: bool, show_stderr: bool) -> Result<()> {
311 let stdout_file = format!("{}.stdout", id); 312 let stdout_file = format!("{}.stdout", id);
312 let stderr_file = format!("{}.stderr", id); 313 let stderr_file = format!("{}.stderr", id);
313 314
@@ -348,7 +349,7 @@ fn cat_logs(id: &str, show_stdout: bool, show_stderr: bool) -> Result<(), Box<dy
348 Ok(()) 349 Ok(())
349} 350}
350 351
351fn tail_logs(id: &str, show_stdout: bool, show_stderr: bool) -> Result<(), Box<dyn std::error::Error>> { 352fn tail_logs(id: &str, show_stdout: bool, show_stderr: bool) -> Result<()> {
352 let stdout_file = format!("{}.stdout", id); 353 let stdout_file = format!("{}.stdout", id);
353 let stderr_file = format!("{}.stderr", id); 354 let stderr_file = format!("{}.stderr", id);
354 355
@@ -464,7 +465,7 @@ fn tail_logs(id: &str, show_stdout: bool, show_stderr: bool) -> Result<(), Box<d
464 Ok(()) 465 Ok(())
465} 466}
466 467
467fn read_file_content(file: &mut File) -> Result<String, Box<dyn std::error::Error>> { 468fn read_file_content(file: &mut File) -> Result<String> {
468 let mut content = String::new(); 469 let mut content = String::new();
469 file.read_to_string(&mut content)?; 470 file.read_to_string(&mut content)?;
470 Ok(content) 471 Ok(content)
@@ -474,7 +475,7 @@ fn handle_file_change(
474 file_path: &str, 475 file_path: &str,
475 positions: &mut std::collections::HashMap<String, u64>, 476 positions: &mut std::collections::HashMap<String, u64>,
476 show_headers: bool 477 show_headers: bool
477) -> Result<(), Box<dyn std::error::Error>> { 478) -> Result<()> {
478 let mut file = File::open(file_path)?; 479 let mut file = File::open(file_path)?;
479 let current_pos = positions.get(file_path).copied().unwrap_or(0); 480 let current_pos = positions.get(file_path).copied().unwrap_or(0);
480 481
@@ -500,7 +501,7 @@ fn handle_file_change(
500 Ok(()) 501 Ok(())
501} 502}
502 503
503fn list_daemons() -> Result<(), Box<dyn std::error::Error>> { 504fn list_daemons() -> Result<()> {
504 println!("{:<20} {:<8} {:<10} {}", "ID", "PID", "STATUS", "COMMAND"); 505 println!("{:<20} {:<8} {:<10} {}", "ID", "PID", "STATUS", "COMMAND");
505 println!("{}", "-".repeat(50)); 506 println!("{}", "-".repeat(50));
506 507
@@ -557,7 +558,7 @@ fn list_daemons() -> Result<(), Box<dyn std::error::Error>> {
557 Ok(()) 558 Ok(())
558} 559}
559 560
560fn status_daemon(id: &str) -> Result<(), Box<dyn std::error::Error>> { 561fn status_daemon(id: &str) -> Result<()> {
561 let pid_file = format!("{}.pid", id); 562 let pid_file = format!("{}.pid", id);
562 let stdout_file = format!("{}.stdout", id); 563 let stdout_file = format!("{}.stdout", id);
563 let stderr_file = format!("{}.stderr", id); 564 let stderr_file = format!("{}.stderr", id);
@@ -614,7 +615,7 @@ fn status_daemon(id: &str) -> Result<(), Box<dyn std::error::Error>> {
614 Ok(()) 615 Ok(())
615} 616}
616 617
617fn clean_orphaned_files() -> Result<(), Box<dyn std::error::Error>> { 618fn clean_orphaned_files() -> Result<()> {
618 tracing::info!("Scanning for orphaned daemon files..."); 619 tracing::info!("Scanning for orphaned daemon files...");
619 620
620 let mut cleaned_count = 0; 621 let mut cleaned_count = 0;