initial commit

This commit is contained in:
Tigor Hutasuhut 2022-08-31 16:22:51 +07:00
commit 16fc4c4e49
7 changed files with 842 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

528
Cargo.lock generated Normal file
View File

@ -0,0 +1,528 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
dependencies = [
"iana-time-zone",
"num-integer",
"num-traits",
"winapi",
]
[[package]]
name = "clap"
version = "3.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68d43934757334b5c0519ff882e1ab9647ac0258b47c24c4f490d78e42697fd5"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "iana-time-zone"
version = "0.1.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"js-sys",
"once_cell",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "indexmap"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "js-sys"
version = "0.3.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "network-on-fail"
version = "0.1.0"
dependencies = [
"clap",
"log",
"retry",
"sensible-env-logger",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
[[package]]
name = "os_str_bytes"
version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "pretty_env_logger"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
dependencies = [
"env_logger",
"log",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "retry"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac95c60a949a63fd2822f4964939662d8f2c16c4fa0624fd954bc6e703b9a3f6"
dependencies = [
"rand",
]
[[package]]
name = "sensible-env-logger"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced68043c576cfe54922c96140aeee81bbf55b419ec61595057ea4301a294f31"
dependencies = [
"chrono",
"log",
"pretty_env_logger",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "unicode-ident"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

14
Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "network-on-fail"
version = "0.1.0"
edition = "2021"
authors = ["Tigor Hutasuhut <tigor.hutasuhut@gmail.com>"]
description = "Program to run command when ping fails"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "3.2.19", features = ["derive", "cargo"] }
log = "0.4.17"
retry = "1.3.1"
sensible-env-logger = { version = "0.3.1", features = ["local-time"] }

86
README.md Normal file
View File

@ -0,0 +1,86 @@
# Network on Fail
Executes a program or script when ping fails to all given target host by certain amount of times.
By default it runs command for `systemctl restart NetworkManager`, which will restart your network
if you use Network Manager as your primary network management and systemd. (Otherwise it fails, duh).
This program does not assume privilege access and thus if a command requires such thing, you must
run this program as a user that can run that command. For example, by using `sudo`.
## Example Usage
```sh
network-on-fail --target myamazingwebsite.com,cool.site.io --exec "echo oh no!"
# or
network-on-fail --target myamazingwebsite.com --target cool.site.io --exec "echo oh no!"
```
Example above will ping (using default ping parameters set by this program) myamazingwebsite.com at
first, then when fails, pings cool.site.io. If that fails too, a counter will then be raised.
When counter reached maximum allowed (default 3), the `exec` command will be launched. In which case
at the example command above, "echo oh no" will be executed.
On success ping, counter will be reset to 0.
# Command and Arguments
```
USAGE:
network-on-fail [OPTIONS]
OPTIONS:
-c, --count <COUNT>
How many ping run fails before executing command. This means that when a ping run fails
(all ping attempt to each target failed), a counter will be raised. When the counter
reached this value, command will be executed then restart back to 0.
A successful ping will put counter value back to 0.
[default: 3]
-d, --delay <DELAY>
Delay between each ping run in seconds. Delay starts ticking after a ping to a host is a
success operation
[default: 10]
-D, --delay-after-exec <DELAY_AFTER_EXEC>
Delay after execute command in seconds
[default: 30]
-e, --exec <EXEC>...
Command to execute when ping fails. Use quotes to handle command with spaces. Repeated
argument will be appended
[default: systemctl restart NetworkManager]
[aliases: command]
[short aliases: C]
-h, --help
Print help information
--ping-count <PING_COUNT>
Ping number of times before exit waiting for target
[default: 1]
-t, --target <TARGET>...
Target hosts of ping. When one ping fails, the programs tries to ping the others first
before rising the counter when all fails
[default: google.com cloudflare.com]
[aliases: ping]
-T, --timeout <TIMEOUT>
Timeout to wait between each ping in seconds
[default: 5]
-V, --version
Print version information
```

6
rustfmt.toml Normal file
View File

@ -0,0 +1,6 @@
hard_tabs = true
max_width = 160
use_field_init_shorthand = true
use_try_shorthand = true
imports_granularity = "Crate"
group_imports = "StdExternalCrate"

199
src/cmd.rs Normal file
View File

@ -0,0 +1,199 @@
use std::{
env,
fmt::{Debug, Display},
process::{Command as Program, Output},
thread,
time::Duration,
};
use clap::{crate_authors, crate_name, crate_version, Parser};
use log::{error, info};
use retry::{delay::Fixed, retry_with_index, OperationResult};
trait Report<T, E> {
fn log(self) -> Result<T, E>;
fn with_log<C, F>(self, context: F) -> Result<T, E>
where
C: Display,
F: FnOnce() -> C;
}
pub type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
impl<T, E> Report<T, E> for std::result::Result<T, E>
where
E: Debug,
{
fn log(self) -> Result<T, E>
where
E: Debug,
{
self.map_err(|err| {
error!("{err:?}");
err
})
}
fn with_log<C, F>(self, context: F) -> Result<T, E>
where
C: Display,
F: FnOnce() -> C,
{
self.map_err(|err| {
error!("{}, {err:#?}", context());
err
})
}
}
const DESC: &str = r#"
Executes a program or script when ping fails to all given target host by certain amount of times.
By default it runs command for `systemctl restart NetworkManager`, which will restart your network if you use Network Manager as your primary network management and systemd.
This program does not assume privilege access and thus if a command requires such thing, you must run this program as a user that can run that command. For example, by using `sudo`.
Example Configured Usage:
network-on-fail --target myamazingwebsite.com,cool.site.io --exec "echo oh no!"
or
network-on-fail --target myamazingwebsite.com --target cool.site.io --exec "echo oh no!"
Example above will ping (using default ping parameters set by this program) myamazingwebsite.com at first, then when fails, pings cool.site.io. If that fails too, a counter will then be raised.
When counter reached maximum allowed (default 3), the `exec` command will be launched. In which case at the example command above, "echo oh no" will be executed.
On success ping, counter will be reset to 0.
"#;
/// Program to run when ping fails to all target.
#[derive(Debug, Parser)]
#[clap(
name(crate_name!()),
author(crate_authors!("\n")),
version(crate_version!()),
about(DESC),
long_about = None,
dont_collapse_args_in_usage(true),
)]
pub struct Command {
/// Target hosts of ping. When one ping fails, the programs tries to ping the others first
/// before rising the counter when all fails.
#[clap(
short,
long,
default_values = &["google.com", "cloudflare.com"],
use_value_delimiter(true),
action(clap::ArgAction::Append),
min_values(1),
value_parser(clap::builder::NonEmptyStringValueParser::new()),
visible_alias("ping"),
)]
target: Vec<String>,
/// Delay between each ping run in seconds. Delay starts ticking after a ping to a host is a success operation.
#[clap(short, long, default_value = "10")]
delay: usize,
/// Delay after execute command in seconds.
#[clap(short('D'), long, default_value = "30")]
delay_after_exec: usize,
/// Timeout to wait between each ping in seconds.
#[clap(short('T'), long, default_value = "5")]
timeout: usize,
/// How many ping run fails before executing command. This means that when a ping run fails
/// (all ping attempt to each target failed), a counter will be raised. When the counter
/// reached this value, command will be executed then restart back to 0.
///
/// A successful ping will put counter value back to 0.
#[clap(short, long, default_value = "3")]
count: usize,
/// Ping number of times before exit waiting for target.
#[clap(long, default_value = "1")]
ping_count: usize,
/// Command to execute when ping fails. Use quotes to handle command with spaces. Repeated
/// argument will be appended.
#[clap(
short('e'),
visible_short_alias('C'),
long,
visible_alias("command"),
default_values = &["systemctl", "restart", "NetworkManager"],
use_value_delimiter(true),
value_delimiter(' '),
action(clap::ArgAction::Append),
min_values(1),
value_parser(clap::builder::NonEmptyStringValueParser::new()),
)]
exec: Vec<String>,
}
impl Command {
pub fn execute(self) -> Result<()> {
info!("Running with Config:\n{self:#?}");
let main = self.exec.get(0).unwrap();
let mut counter = 0;
let sleep: u64 = self.delay_after_exec.try_into().unwrap();
let timeout = self.timeout.to_string();
let ping_count = self.ping_count.to_string();
let cmd_display = self.exec.join(" ");
'looper: loop {
if counter >= self.count {
info!("counter limit is reached. executing command '{cmd_display}'");
counter = 0;
let out = retry_with_index(Fixed::from_millis(100), |n| {
if n > 3 {
return OperationResult::Err(format!("failed executing command '{cmd_display}' for three times!",));
}
let v = Program::new(main).args(&self.exec[1..]).output().log();
let output = match v {
Ok(output) => output,
Err(err) => return OperationResult::Retry(err.to_string()),
};
if output.status.success() {
OperationResult::Ok(output)
} else {
let s = get_output(&output);
error!("{s}");
OperationResult::Retry(s)
}
})
.log();
if let Ok(out) = out {
info!("{}", get_output(&out));
if out.status.success() {
info!("pausing for {sleep} seconds");
thread::sleep(Duration::from_secs(sleep));
}
}
}
for s in &self.target {
info!("executing ping -c {ping_count} -w {timeout} {s}");
let output = Program::new("ping").args(["-c", &ping_count, "-w", &timeout, s]).output().log()?;
if output.status.success() {
info!("ping to {s} succeed. resetting counter");
counter = 0;
thread::sleep(Duration::from_secs(self.delay.try_into().unwrap()));
continue 'looper;
} else {
error!("{}", get_output(&output))
}
}
info!("increasing counter from {counter} to {} for maximum {}", counter + 1, self.count);
counter += 1;
thread::sleep(Duration::from_secs(self.delay.try_into().unwrap()));
}
}
}
fn get_output(io_out: &Output) -> String {
let v = io_out.stdout.iter().chain(io_out.stderr.iter()).copied().collect::<Vec<u8>>();
String::from_utf8_lossy(&v).to_string()
}

8
src/main.rs Normal file
View File

@ -0,0 +1,8 @@
pub mod cmd;
use clap::Parser;
fn main() -> cmd::Result<()> {
std::env::set_var("RUST_LOG", "info");
sensible_env_logger::init_timed_local!();
cmd::Command::parse().execute()
}