322 lines
8.7 KiB
Rust
322 lines
8.7 KiB
Rust
//! CAI-Watchdog is a lightweigth watchdog for *nix and Windows
|
|
//! Author: Alexander I. Chebykin (CAI) <alex.chebykin@gmail.com>
|
|
|
|
#[macro_use]
|
|
extern crate ini;
|
|
extern crate exitcode;
|
|
|
|
use std::env;
|
|
use std::ffi::OsStr;
|
|
use std::path::Path;
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
use sysinfo::System;
|
|
|
|
mod mods;
|
|
|
|
use crate::mods::mod_debug::*;
|
|
use crate::mods::mod_fs::*;
|
|
use crate::mods::mod_i18n::*;
|
|
use crate::mods::mod_os::*;
|
|
use crate::mods::mod_tasks::*;
|
|
|
|
/// Check rule
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `rule` Rule to be checked
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// if check(&tasks[i]).await {
|
|
/// println!("ok");
|
|
/// } else {
|
|
/// println!("uh-oh... something wrong!");
|
|
/// }
|
|
/// ```
|
|
async fn check(rule: &Rule) -> bool {
|
|
return if rule.uri.to_string() != "".to_string() {
|
|
check_uri(rule.uri.clone()).await
|
|
} else {
|
|
check_process(rule.process.clone())
|
|
};
|
|
}
|
|
|
|
/// Check is process running
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `process_name` Process name to be checked
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// if check_process("httpd".to_string()).await {
|
|
/// println!("ok");
|
|
/// } else {
|
|
/// println!("uh-oh... something wrong!");
|
|
/// }
|
|
/// ```
|
|
fn check_process(process_name: String) -> bool {
|
|
let mut sys = System::new_all();
|
|
let mut result: bool = false;
|
|
|
|
sys.refresh_all();
|
|
|
|
for _process in sys.processes_by_exact_name(OsStr::new(&process_name)) {
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// Checks web-service availability
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `uri` - Service URI to be checked
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// if check_uri("https://somesite.local/api/v1/".to_string()).await {
|
|
/// println!("ok");
|
|
/// } else {
|
|
/// println!("uh-oh... something wrong!");
|
|
/// }
|
|
/// ```
|
|
async fn check_uri(uri: String) -> bool {
|
|
if let Err(_e) = reqwest::get(uri).await {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// Print help and program version information
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `args` - Command-line arguments
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// let args: Vec<String> = env::args().collect();
|
|
///
|
|
/// print_help(args.clone());
|
|
/// ```
|
|
fn print_help(args: Vec<String>) {
|
|
let locale = Locale::new();
|
|
|
|
if cfg!(windows) {
|
|
if args.len() > 1 && (args[1].to_string() == "/help".to_string() || args[1].to_string() == "/?".to_string()) {
|
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
println!("CAI Watchdog {} {}", locale.t().ver, VERSION);
|
|
println!("");
|
|
println!("Usage: {} [/? | /help | /v | /ver | config_file]", &args[0]);
|
|
println!(" /? | /help : {}", locale.t().this_help_message);
|
|
println!(" /v | /ver : {}", locale.t().version_info);
|
|
println!(" config_file : {}", locale.t().configuration_file);
|
|
|
|
std::process::exit(exitcode::OK);
|
|
} else if args.len() > 1
|
|
&& (args[1].to_string() == "/ver".to_string() || args[1].to_string() == "/v".to_string()) {
|
|
|
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
println!("CAI Watchdog {} {}", locale.t().ver, VERSION);
|
|
|
|
std::process::exit(exitcode::OK);
|
|
}
|
|
} else {
|
|
if args.len() > 1 && (args[1].to_string() == "--help".to_string() || args[1].to_string() == "-h".to_string()) {
|
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
println!("CAI Watchdog {} {}", locale.t().ver, VERSION);
|
|
println!("");
|
|
println!("{}: {} [-h | --help | -v | --ver | config_file]", locale.t().usage, &args[0]);
|
|
println!(" -h | --help : {}", locale.t().this_help_message);
|
|
println!(" -v | --ver : {}", locale.t().version_info);
|
|
println!(" config_file : {}", locale.t().configuration_file);
|
|
|
|
std::process::exit(exitcode::OK);
|
|
} else if args.len() > 1
|
|
&& (args[1].to_string() == "--ver".to_string() || args[1].to_string() == "-v".to_string()) {
|
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
println!("CAI Watchdog {} {}", locale.t().ver, VERSION);
|
|
|
|
std::process::exit(exitcode::OK);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let locale = Locale::new();
|
|
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
print_help(args.clone());
|
|
|
|
let mut config_file = get_exe_path();
|
|
|
|
if cfg!(windows) {
|
|
config_file = format!("{}\\cai-watchdog.ini", config_file);
|
|
} else {
|
|
config_file = "/etc/cai-watchdog/cai-watchdog.conf".to_string();
|
|
}
|
|
|
|
let cfg_file = if args.len() > 1 {
|
|
&args[1]
|
|
} else {
|
|
&config_file
|
|
};
|
|
|
|
if !Path::new(cfg_file).exists() {
|
|
println!("\u{26a0} {}! {}.",
|
|
locale.t().error,
|
|
locale.t().cant_find_config_file
|
|
);
|
|
println!("{}", locale.t().exiting);
|
|
|
|
std::process::exit(exitcode::CONFIG);
|
|
}
|
|
|
|
let cfg = ini!(cfg_file);
|
|
|
|
let check_interval = if cfg["main"].contains_key("check_interval") {
|
|
cfg["main"]["check_interval"].clone().unwrap().parse::<u64>().unwrap() * 1000
|
|
} else {
|
|
10000
|
|
};
|
|
|
|
let rules_count = if cfg["main"].contains_key("check_interval") {
|
|
cfg["main"]["rules_count"].clone().unwrap().parse::<u8>().unwrap()
|
|
} else {
|
|
0
|
|
};
|
|
|
|
let mut tasks_prc = vec![];
|
|
let mut tasks_web = vec![];
|
|
|
|
for i in 1..rules_count + 1 {
|
|
let service = if cfg[&format!("rule{}", i)].contains_key("service") {
|
|
cfg[&format!("rule{}", i)]["service"].clone().unwrap()
|
|
} else {
|
|
format!("Service {}", i)
|
|
};
|
|
|
|
let uri = if cfg[&format!("rule{}", i)].contains_key("uri") {
|
|
cfg[&format!("rule{}", i)]["uri"].clone().unwrap()
|
|
} else {
|
|
"".to_string()
|
|
};
|
|
|
|
let process = if cfg[&format!("rule{}", i)].contains_key("process") {
|
|
cfg[&format!("rule{}", i)]["process"].clone().unwrap()
|
|
} else {
|
|
"".to_string()
|
|
};
|
|
|
|
let email = if cfg[&format!("rule{}", i)].contains_key("email") {
|
|
cfg[&format!("rule{}", i)]["email"].clone().unwrap()
|
|
} else {
|
|
"".to_string()
|
|
};
|
|
|
|
let command = if cfg[&format!("rule{}", i)].contains_key("command") {
|
|
cfg[&format!("rule{}", i)]["command"].clone().unwrap()
|
|
} else {
|
|
"".to_string()
|
|
};
|
|
|
|
debug_log(format!("rule {}", i));
|
|
debug_log(format!("service {}", service));
|
|
debug_log(format!("uri {}", uri));
|
|
debug_log(format!("process {}", process));
|
|
debug_log(format!("email {}", email));
|
|
debug_log(format!("command {}", command));
|
|
|
|
if uri != "".to_string() {
|
|
tasks_web.push(
|
|
Rule{
|
|
service: service,
|
|
uri: uri,
|
|
process: process,
|
|
email: email,
|
|
command: command,
|
|
last_state: false,
|
|
}
|
|
);
|
|
} else {
|
|
tasks_prc.push(
|
|
Rule{
|
|
service: service,
|
|
uri: uri,
|
|
process: process,
|
|
email: email,
|
|
command: command,
|
|
last_state: false,
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
let on_start_command = if cfg["main"].contains_key("on_start_command") {
|
|
cfg["main"]["on_start_command"].clone().unwrap()
|
|
} else {
|
|
"".to_string()
|
|
};
|
|
|
|
debug_log(format!("\u{2139} {}", locale.t().service_started));
|
|
|
|
if on_start_command.to_string() != "" {
|
|
execute(on_start_command);
|
|
}
|
|
|
|
let mut just_started_web = true;
|
|
|
|
std::thread::spawn(move || {
|
|
loop {
|
|
for i in 0..tasks_web.len() {
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
|
|
rt.block_on(async {
|
|
if check(&tasks_web[i]).await {
|
|
execute_web_task(&mut tasks_web[i], true, just_started_web);
|
|
} else {
|
|
execute_web_task(&mut tasks_web[i], false, just_started_web);
|
|
}
|
|
});
|
|
}
|
|
|
|
just_started_web = false;
|
|
|
|
thread::sleep(Duration::from_millis(check_interval));
|
|
}
|
|
});
|
|
|
|
let mut just_started_prc = true;
|
|
|
|
loop {
|
|
for i in 0..tasks_prc.len() {
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
|
|
rt.block_on(async {
|
|
if check(&tasks_prc[i]).await {
|
|
execute_os_task(&mut tasks_prc[i], true, just_started_prc);
|
|
} else {
|
|
execute_os_task(&mut tasks_prc[i], false, just_started_prc);
|
|
}
|
|
});
|
|
}
|
|
|
|
just_started_prc = false;
|
|
|
|
thread::sleep(Duration::from_millis(check_interval));
|
|
}
|
|
}
|