Initial commit.
This commit is contained in:
133
src/main.rs
Normal file
133
src/main.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
extern crate chrono;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
#[macro_use]
|
||||
extern crate structopt;
|
||||
extern crate toml;
|
||||
|
||||
use std::process;
|
||||
use std::time::Duration;
|
||||
use std::thread;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::fs;
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use chrono::prelude::*;
|
||||
use structopt::StructOpt;
|
||||
|
||||
fn ping(host: &str) -> Result<&str, &str> {
|
||||
let result = process::Command::new("ping")
|
||||
.args(&["-c", "1"])
|
||||
.args(&["-t", "3"]) // Should be -w on linux
|
||||
.arg(host)
|
||||
.stdout(process::Stdio::null())
|
||||
.stderr(process::Stdio::null())
|
||||
.status()
|
||||
.map_err(|_| host)?;
|
||||
|
||||
if result.success() {
|
||||
Ok(host)
|
||||
} else {
|
||||
Err(host)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(StructOpt)]
|
||||
#[structopt(name = "ips-uptime")]
|
||||
struct Opt {
|
||||
#[structopt(parse(from_os_str))]
|
||||
config: PathBuf
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Config {
|
||||
command: HashMap<String, Command>,
|
||||
hosts: Vec<Host>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Command {
|
||||
command: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Host {
|
||||
name: String,
|
||||
host: String,
|
||||
command: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opt = Opt::from_args();
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
|
||||
fs::File::open(&opt.config)
|
||||
.and_then(|mut file| file.read_to_end(&mut buffer))
|
||||
.expect("failed to read config");
|
||||
|
||||
let config: Config = toml::from_slice(&buffer).expect("failed to parse config");
|
||||
|
||||
println!("config: {:#?}", config);
|
||||
|
||||
process::exit(0);
|
||||
|
||||
// Cloudflare/APNIC DNS (primary): 1.1.1.1
|
||||
// Cloudflare/APNIC DNS (secondary): 1.0.0.1
|
||||
// Google DNS (primary): 8.8.8.8
|
||||
// Google DNS (secondary): 8.8.4.4
|
||||
|
||||
let mut status: Option<DateTime<Utc>> = None;
|
||||
|
||||
loop {
|
||||
let now = Utc::now();
|
||||
|
||||
let result = ping("1.1.1.1")
|
||||
.or_else(|_host| {
|
||||
// println!("failed to ping {}", host);
|
||||
|
||||
ping("1.0.0.1")
|
||||
})
|
||||
.or_else(|_host| {
|
||||
// println!("failed to ping {}", host);
|
||||
|
||||
ping("8.8.8.8")
|
||||
})
|
||||
.or_else(|_host| {
|
||||
// println!("failed to ping {}", host);
|
||||
|
||||
ping("8.8.4.4")
|
||||
})
|
||||
.or_else(|host| {
|
||||
// println!("failed to ping {}", host);
|
||||
|
||||
Err(host)
|
||||
})
|
||||
.and_then(|host| {
|
||||
// println!("success to ping {}", host);
|
||||
|
||||
Ok(host)
|
||||
});
|
||||
|
||||
|
||||
if result.is_ok() {
|
||||
if let Some(down) = status {
|
||||
let now = Utc::now();
|
||||
|
||||
println!(" - {}, duration: {}", now, (now - down));
|
||||
|
||||
status = None;
|
||||
}
|
||||
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
} else {
|
||||
if status.is_none() {
|
||||
print!("{}", now);
|
||||
io::stdout().flush().expect("failed to flush stdout");
|
||||
|
||||
status = Some(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user