Compare commits
No commits in common. "3f96d27ee9b8b26b1c3179f5fc3388ad566072e2" and "239197ffed5fb1417a3b712458f6683f34aa9587" have entirely different histories.
3f96d27ee9
...
239197ffed
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,11 +0,0 @@
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Build files
|
||||
target
|
||||
1083
Cargo.lock
generated
1083
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
17
Cargo.toml
17
Cargo.toml
@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "cai-watchdog"
|
||||
version = "0.1.0"
|
||||
authors = ["Alexander I. Chebykin <alex.chebykin@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
file-utils = "0.1.5"
|
||||
chrono = "0.4.19"
|
||||
# Sync
|
||||
#reqwest = { version = "0.11", features = ["blocking"] }
|
||||
# Async
|
||||
reqwest = "0.11"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
ini = "1.3.0"
|
||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Alexander I. Chebykin <alex.chebykin@gmail.com>
|
||||
Copyright (c) <year> <copyright holders>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
[main]
|
||||
check_interval = 10000
|
||||
rules_count = 2
|
||||
[rule1]
|
||||
address = http://127.0.0.1:3000/api/v1/
|
||||
email = admin@server.local
|
||||
[rule2]
|
||||
address = http://127.0.0.1:3300/api/v1/
|
||||
email = admin@server.local
|
||||
@ -1,16 +0,0 @@
|
||||
[Unit]
|
||||
Description=Watchdog service
|
||||
|
||||
[Service]
|
||||
User=wwwrun
|
||||
Group=www
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/cai-watchdog
|
||||
|
||||
KillMode=control-group
|
||||
NotifyAccess=all
|
||||
SuccessExitStatus=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=cai_watchdog
|
||||
@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
GROUP_ID=<group_id>
|
||||
BOT_TOKEN=<bot_token>
|
||||
|
||||
# this 3 checks (if) are not necessary but should be convenient
|
||||
if [ "$1" == "-h" ]; then
|
||||
echo "Usage: `basename $0` \"text message\""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Add message text as second arguments"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "You can pass only one argument. For string with spaces put it on quotes"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
curl -s --data "text=$1" --data "chat_id=$GROUP_ID" 'https://api.telegram.org/bot'$BOT_TOKEN'/sendMessage' > /dev/null
|
||||
@ -1,11 +0,0 @@
|
||||
Function Send-Mail {
|
||||
$EmailFrom = "yourmailadress@somedomain.com"
|
||||
$EmailTo = $args[0]
|
||||
$Subject = $args[1]
|
||||
$Body = $args[0]
|
||||
$SMTPServer = "smtp.somedomain.com"
|
||||
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
|
||||
$SMTPClient.EnableSsl = $true
|
||||
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("usr", "pass");
|
||||
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
Function Send-Telegram {
|
||||
Param([Parameter(Mandatory=$true)][String]$Message)
|
||||
|
||||
$Telegramtoken = "Your_Telegram_Token"
|
||||
$Telegramchatid = "Your_Telegram_Chat_ID"
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
$Response = Invoke-RestMethod -Uri "https://api.telegram.org/bot$($Telegramtoken)/sendMessage?chat_id=$($Telegramchatid)&text=$($Message)"
|
||||
}
|
||||
176
src/main.rs
176
src/main.rs
@ -1,176 +0,0 @@
|
||||
#[macro_use]
|
||||
extern crate ini;
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::process::Command;
|
||||
|
||||
/// Rule description structure
|
||||
pub struct Rule {
|
||||
/// Monitored service name
|
||||
pub service: String,
|
||||
/// Monitored URI
|
||||
pub address: String,
|
||||
/// E-mail address for messages
|
||||
pub email: String,
|
||||
/// This command will be executed on state change
|
||||
pub command: String,
|
||||
/// Last state
|
||||
pub last_state: bool,
|
||||
}
|
||||
|
||||
/// Checks service availability
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uri` - Service URI to be checked
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// if if check("https://somesite.local/api/v1/".to_string()).await {
|
||||
/// println!("ok");
|
||||
/// } else {
|
||||
/// println!("uh-oh... something wrong!");
|
||||
/// }
|
||||
/// ```
|
||||
async fn check(uri: String) -> bool {
|
||||
if let Err(_e) = reqwest::get(uri).await {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Output to console only in debug version
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `text` - Message text
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// debug_log("Debug version started".to_string());
|
||||
/// ```
|
||||
fn debug_log(text: String) {
|
||||
if cfg!(debug_assertions) {
|
||||
println!("{}", text);
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute shell command
|
||||
///
|
||||
/// In linux sh command interpreter will be called.
|
||||
/// In Windows PowerShell command interpreter will be called.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `command` - Command to be executed
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// execute("gedit".to_string());
|
||||
/// ```
|
||||
fn execute(command: String) {
|
||||
debug_log(format!("execute {}", command));
|
||||
|
||||
let output = if cfg!(target_os = "windows") {
|
||||
Command::new("powershell")
|
||||
.args(["-NoLogo", "-NonInteractive", "-Command", &command])
|
||||
.output()
|
||||
.expect("failed to execute process")
|
||||
} else {
|
||||
Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&command)
|
||||
.output()
|
||||
.expect("failed to execute process")
|
||||
};
|
||||
|
||||
let result = output.stdout;
|
||||
debug_log(format!("{:?}", result));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cfg_file = if cfg!(windows) {
|
||||
"cai-watchdog.cfg"
|
||||
} else {
|
||||
"/etc/cai-watchdog.cfg"
|
||||
};
|
||||
|
||||
let cfg = ini!(cfg_file);
|
||||
|
||||
let check_interval = cfg["main"]["check_interval"].clone().unwrap().parse::<u64>().unwrap();
|
||||
let rules_count = cfg["main"]["rules_count"].clone().unwrap().parse::<u8>().unwrap();
|
||||
|
||||
let mut tasks = vec![];
|
||||
|
||||
for i in 1..rules_count + 1 {
|
||||
let service = cfg[&format!("{}{}", "rule", i)]["service"].clone().unwrap();
|
||||
let address = cfg[&format!("{}{}", "rule", i)]["address"].clone().unwrap();
|
||||
let email = cfg[&format!("{}{}", "rule", i)]["email"].clone().unwrap();
|
||||
let command = cfg[&format!("{}{}", "rule", i)]["command"].clone().unwrap();
|
||||
|
||||
debug_log(format!("rule {}", i));
|
||||
debug_log(format!("service {}", service));
|
||||
debug_log(format!("address {}", address));
|
||||
debug_log(format!("email {}", email));
|
||||
debug_log(format!("command {}", command));
|
||||
|
||||
tasks.push(
|
||||
Rule{
|
||||
service: cfg[&format!("{}{}", "rule", i)]["service"].clone().unwrap().to_string(),
|
||||
address: cfg[&format!("{}{}", "rule", i)]["address"].clone().unwrap().to_string(),
|
||||
email: cfg[&format!("{}{}", "rule", i)]["email"].clone().unwrap().to_string(),
|
||||
command: cfg[&format!("{}{}", "rule", i)]["command"].clone().unwrap().to_string(),
|
||||
last_state: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loop {
|
||||
for i in 0..tasks.len() {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
if check(tasks[i].address.clone()).await {
|
||||
if tasks[i].last_state != true {
|
||||
debug_log(format!("{} state changed to true", tasks[i].address));
|
||||
|
||||
let shell_cmd = tasks[i].command.to_string()
|
||||
.replace("<email>", &tasks[i].email)
|
||||
.replace("<header>", &format!("\"Service {} ({}) online\"", tasks[i].service, tasks[i].address))
|
||||
.replace("<message>", &format!("\"Service {} ({}) is now online\"", tasks[i].service, tasks[i].address));
|
||||
|
||||
debug_log(format!("execute {}", shell_cmd));
|
||||
|
||||
execute(shell_cmd);
|
||||
}
|
||||
|
||||
debug_log(format!("{} check is ok", tasks[i].address));
|
||||
|
||||
tasks[i].last_state = true
|
||||
} else {
|
||||
if tasks[i].last_state != false {
|
||||
debug_log(format!("{} state changed to false", tasks[i].address));
|
||||
|
||||
let shell_cmd = tasks[i].command.to_string()
|
||||
.replace("<email>", &tasks[i].email)
|
||||
.replace("<header>", &format!("\"Service {} ({}) offline\"", tasks[i].service, tasks[i].address))
|
||||
.replace("<message>", &format!("\"Service {} ({}) is now offline\"", tasks[i].service, tasks[i].address));
|
||||
|
||||
debug_log(format!("execute {}", shell_cmd));
|
||||
execute(shell_cmd);
|
||||
}
|
||||
|
||||
debug_log(format!("{} check failed", tasks[i].address));
|
||||
|
||||
tasks[i].last_state = false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
thread::sleep(Duration::from_millis(check_interval));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user