now can run
This commit is contained in:
122
src/main.rs
122
src/main.rs
@@ -1,9 +1,23 @@
|
||||
use std::process::Command;
|
||||
use std::{
|
||||
fs,
|
||||
panic,
|
||||
thread,
|
||||
time::Duration,
|
||||
process::Command,
|
||||
sync::Arc,
|
||||
};
|
||||
use chrono::prelude::*;
|
||||
use serde::{ Deserialize, Serialize, };
|
||||
use rust_util::util_msg::{ print_info, print_error, };
|
||||
use rust_util::{
|
||||
util_file::locate_file,
|
||||
util_msg::{ print_info, print_error, print_debug, }
|
||||
};
|
||||
use dingtalk::DingTalk;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct KeepRunningConfig {
|
||||
check_inverval_secs: Option<u64>,
|
||||
show_debug_output: Option<bool>,
|
||||
notify_token: String,
|
||||
items: Vec<KeepRunningConfigItem>,
|
||||
}
|
||||
@@ -15,18 +29,91 @@ struct KeepRunningConfigItem {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
print_info("Start run: ps aux");
|
||||
let output_str = match ps_aux() {
|
||||
Some(output_str) => output_str, None => return,
|
||||
};
|
||||
let lines = read_str_to_lines(&output_str);
|
||||
panic::set_hook(Box::new(|panic_info| {
|
||||
print_error(&format!("Panic in running keeprunningd: {:?}", panic_info));
|
||||
}));
|
||||
|
||||
// println!("{}", output_str);
|
||||
// for ln in &lines {
|
||||
// println!(">>>>>>> {}", ln);
|
||||
// }
|
||||
println!("{:?}", lines.iter().filter(|ln| ln.contains("java") && ln.contains("aaa")).collect::<Vec<_>>());
|
||||
println!("{}", lines.len());
|
||||
let config_file_opt = locate_file(&[
|
||||
"keeprunningd.json".into(),
|
||||
"~/keeprunningd.json".into(),
|
||||
"/etc/keeprunningd.json".into()
|
||||
]);
|
||||
|
||||
let config_file = match config_file_opt {
|
||||
None => {
|
||||
print_error("Cannot find config file!");
|
||||
return;
|
||||
},
|
||||
Some(config_file) => {
|
||||
print_info(&format!("Find config file: {:?}", &config_file));
|
||||
config_file
|
||||
},
|
||||
};
|
||||
|
||||
let config_file_content = match fs::read_to_string(&config_file) {
|
||||
Ok(c) => c, Err(err) => {
|
||||
print_error(&format!("Read config file {:?}, error: {}", &config_file, err));
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
let keep_running_config: KeepRunningConfig = match serde_json::from_str(&config_file_content) {
|
||||
Ok(c) => c, Err(err) => {
|
||||
print_error(&format!("Parse config file: {:?}, error: {}", &config_file, err));
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
if keep_running_config.show_debug_output.unwrap_or(false) {
|
||||
if let Ok(json) = serde_json::to_string_pretty(&keep_running_config) {
|
||||
print_debug(&format!("Config: {}", json));
|
||||
}
|
||||
}
|
||||
|
||||
let keep_running_config: Arc<KeepRunningConfig> = Arc::new(keep_running_config);
|
||||
for check_cnt in 0.. {
|
||||
print_info(&format!("Check index: {} @{:?}", check_cnt, Local::now()));
|
||||
keep_runningd(keep_running_config.clone());
|
||||
thread::sleep(Duration::from_secs(keep_running_config.check_inverval_secs.unwrap_or(60 * 60)));
|
||||
}
|
||||
}
|
||||
|
||||
fn keep_runningd(keep_running_config: Arc<KeepRunningConfig>) {
|
||||
let t = thread::spawn(move || {
|
||||
let ps_aux_lines = read_str_to_lines(&match ps_aux() { Some(p) => p, None => return, });
|
||||
for keep_running_config_item in &keep_running_config.items {
|
||||
let check_lines = ps_aux_lines.iter().filter(|ln| {
|
||||
keep_running_config_item.grep_tokens.iter().all(|t| ln.contains(t))
|
||||
}).collect::<Vec<_>>();
|
||||
if check_lines.is_empty() { // if check fail!
|
||||
print_info("Send DingTalk notification!");
|
||||
use tokio::runtime;
|
||||
match runtime::Builder::new().basic_scheduler().enable_all().build() {
|
||||
Err(err) => print_error(&format!("Prepare tokio runtime error: {}", err)),
|
||||
Ok(mut rt) => {
|
||||
let mut sb = String::with_capacity(1024);
|
||||
sb.push_str(&format!("Check failed: {}", &keep_running_config_item.title));
|
||||
sb.push_str(&format!("\ncheck time: {:?}", Local::now()));
|
||||
rt.block_on(send_notify(&keep_running_config.notify_token, &sb));
|
||||
},
|
||||
}
|
||||
} else if keep_running_config.show_debug_output.unwrap_or(false) {
|
||||
print_debug(&format!("Find: {:?}", &check_lines));
|
||||
}
|
||||
}
|
||||
});
|
||||
if let Err(err) = t.join() {
|
||||
print_error(&format!("Join check thread error: {:?}", err));
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_notify(notify_token: &str, text: &str) {
|
||||
match DingTalk::from_token(¬ify_token) {
|
||||
Err(err) => print_error(&format!("Prepare DingTalk error: {}", err)),
|
||||
Ok(dt) => if let Err(err) = dt.send_text(text).await {
|
||||
print_error(&format!("Send DingTalk message error: {}", err));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn ps_aux() -> Option<String> {
|
||||
@@ -39,16 +126,17 @@ fn ps_aux() -> Option<String> {
|
||||
},
|
||||
};
|
||||
match String::from_utf8(output.stdout) {
|
||||
Ok(output_str) => Some(output_str), Err(err) => {
|
||||
Ok(output_str) => Some(output_str),
|
||||
Err(err) => {
|
||||
print_error(&format!("Get ps output as utf8 error: {}", err));
|
||||
return None;
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Split string to lines, splited by '\r', '\n' or "\r\n"
|
||||
fn read_str_to_lines(s: &str) -> Vec<String> {
|
||||
let mut r = vec![];
|
||||
|
||||
let mut line = String::new();
|
||||
let mut cs = s.chars();
|
||||
while let Some(c) = cs.next() {
|
||||
@@ -64,6 +152,8 @@ fn read_str_to_lines(s: &str) -> Vec<String> {
|
||||
} else {
|
||||
line.push(nc);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user