improve ping behaviour
This commit is contained in:
parent
d71e515050
commit
fa04e70d44
1002
Cargo.lock
generated
1002
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,8 @@ anyhow = "1.0.86"
|
|||||||
dns-lookup = "2.0.4"
|
dns-lookup = "2.0.4"
|
||||||
mountinfo = "0.2.0"
|
mountinfo = "0.2.0"
|
||||||
ping = "0.5.2"
|
ping = "0.5.2"
|
||||||
sys-mount = "3.0.1"
|
sys-mount = {version="3.0.1", default-features = false}
|
||||||
|
notify-rust = "4"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "automount"
|
name = "automount"
|
||||||
|
118
src/main.rs
118
src/main.rs
@ -1,64 +1,96 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dns_lookup::lookup_host;
|
use dns_lookup::lookup_host;
|
||||||
use mountinfo::{MountInfo, ReadWrite, MountPoint};
|
use mountinfo::{MountInfo, ReadWrite, MountPoint};
|
||||||
|
use notify_rust::Notification;
|
||||||
use ping::{dgramsock, rawsock::ping};
|
use ping::{dgramsock, rawsock::ping};
|
||||||
use std::{ffi::OsStr, fs, path::PathBuf, sync::mpsc::{self, Receiver, Sender}, thread, time::Duration};
|
use std::{ffi::OsStr, fs, net::IpAddr, path::PathBuf, sync::mpsc::{self, Receiver, Sender}, thread::{self, sleep}, time::Duration};
|
||||||
use sys_mount::{unmount, UnmountFlags};
|
use sys_mount::{unmount, UnmountFlags};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mtab = MountInfo::new().unwrap();
|
|
||||||
let mounting_points = mtab.mounting_points;
|
loop {
|
||||||
let relevant_mounts = mounting_points.iter().filter(|&mount_point| {
|
let mtab = MountInfo::new().unwrap();
|
||||||
match &mount_point.fstype {
|
let mounting_points = mtab.mounting_points;
|
||||||
mountinfo::FsType::Other(fsstring) => match fsstring.as_str() {
|
let relevant_mounts = mounting_points.iter().filter(|&mount_point| {
|
||||||
"cifs" => {
|
match &mount_point.fstype {
|
||||||
true
|
mountinfo::FsType::Other(fsstring) => match fsstring.as_str() {
|
||||||
|
"cifs" => {
|
||||||
|
true
|
||||||
|
},
|
||||||
|
_ => false
|
||||||
},
|
},
|
||||||
_ => false
|
_ => false
|
||||||
},
|
}
|
||||||
_ => false
|
});
|
||||||
|
|
||||||
|
for mount_point in relevant_mounts {
|
||||||
|
let path = mount_point.path.to_owned();
|
||||||
|
let fstype = match &mount_point.fstype {
|
||||||
|
mountinfo::FsType::Other(fsstring) => fsstring,
|
||||||
|
_ => ""
|
||||||
|
};
|
||||||
|
let what = &mount_point.what;
|
||||||
|
//println!("Processing {fstype} @ {path:?} from {what}");
|
||||||
|
process_mount(fstype, what, path);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
sleep(Duration::from_secs(5));
|
||||||
|
|
||||||
println!("Scanning for hanging mounts");
|
|
||||||
for mount_point in relevant_mounts {
|
|
||||||
let path = mount_point.path.to_owned();
|
|
||||||
let fstype = match &mount_point.fstype {
|
|
||||||
mountinfo::FsType::Other(fsstring) => fsstring,
|
|
||||||
_ => ""
|
|
||||||
};
|
|
||||||
let what = &mount_point.what;
|
|
||||||
println!("Processing {fstype} @ {path:?} from {what}");
|
|
||||||
process_mount(fstype, what, path);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ping_unreachable(host: &IpAddr, repeat:u8 ) -> bool{
|
||||||
|
for _attempt in 0..repeat {
|
||||||
|
match ping::ping(host.to_owned(),Some(Duration::from_millis(100)),Some(10),None, None, None) {
|
||||||
|
Ok(_) => {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("All ping failed with error -> unmount");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_mount(fstype: &str, what: &String, path: PathBuf) {
|
fn process_mount(fstype: &str, what: &String, path: PathBuf) {
|
||||||
|
let mut higher_timeout = false;
|
||||||
|
let mut failed_initial_check = false;
|
||||||
match fstype {
|
match fstype {
|
||||||
"cifs" => {
|
"cifs" => {
|
||||||
let path_parts = what.replace("//","/");
|
let path_parts = what.replace("//","/");
|
||||||
let host = path_parts.split("/").nth(1).unwrap();
|
let host = path_parts.split("/").nth(1).unwrap();
|
||||||
println!("Checking ping to host {host}");
|
|
||||||
let ips = lookup_host(host).unwrap();
|
let ips = lookup_host(host).unwrap();
|
||||||
let ip = ips.first().unwrap();
|
let ip = ips.first().unwrap();
|
||||||
println!("Using ip {ip:?}");
|
failed_initial_check = ping_unreachable(&ip, 5);
|
||||||
match ping::ping(ip.to_owned(),Some(Duration::from_millis(100)),Some(10),None, None, None) {
|
higher_timeout = true;
|
||||||
Ok(_) => {
|
|
||||||
println!("Ping ok, proceeding")
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
println!("Ping failed with errror {err:?} -> unmount");
|
|
||||||
remove_mount(path.as_os_str());
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if failed_initial_check {
|
||||||
|
let path_utf8 = path.as_os_str().to_string_lossy();
|
||||||
|
let body = format!("Unmounted {} due to fail online check", path_utf8);
|
||||||
|
|
||||||
let timeout = Duration::from_millis(500);
|
let _ = Notification::new()
|
||||||
println!("Checking file access timeout {timeout:?}");
|
.summary("Autounmount")
|
||||||
|
.body(body.as_str())
|
||||||
|
.icon("firefox")
|
||||||
|
.show();
|
||||||
|
|
||||||
|
remove_mount(path.as_os_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let timeout = if higher_timeout {
|
||||||
|
Duration::from_millis(10000)
|
||||||
|
} else {
|
||||||
|
Duration::from_millis(1000)
|
||||||
|
};
|
||||||
let (sender, receiver) = mpsc::channel();
|
let (sender, receiver) = mpsc::channel();
|
||||||
let path_copy = path.clone();
|
let path_copy = path.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
@ -79,15 +111,25 @@ fn process_mount(fstype: &str, what: &String, path: PathBuf) {
|
|||||||
let read_successful = receiver.recv_timeout(timeout);
|
let read_successful = receiver.recv_timeout(timeout);
|
||||||
match read_successful {
|
match read_successful {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("passed, mount still valid")
|
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("Listing failed with errror {err:?} -> unmount");
|
println!("Listing failed with errror {err:?} -> unmount");
|
||||||
|
|
||||||
|
let path_utf8 = path.as_os_str().to_string_lossy();
|
||||||
|
let body = format!("Unmounted {} due to fs operation check timeout out after {}s", path_utf8, timeout.as_secs());
|
||||||
|
|
||||||
|
let _ = Notification::new()
|
||||||
|
.summary("Autounmount")
|
||||||
|
.body(body.as_str())
|
||||||
|
.icon("firefox")
|
||||||
|
.show();
|
||||||
|
|
||||||
|
|
||||||
remove_mount(path.as_os_str());
|
remove_mount(path.as_os_str());
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_mount(path: &OsStr){
|
fn remove_mount(path: &OsStr){
|
||||||
//unmount(path, UnmountFlags::FORCE | UnmountFlags::DETACH).unwrap()
|
unmount(path, UnmountFlags::FORCE | UnmountFlags::DETACH).unwrap()
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user