Skip to content

Commit 66b9c1f

Browse files
authored
Update ssh.rs
1 parent 602de2e commit 66b9c1f

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/ssh.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ pub struct SSHConnection {
1515
sftp: Option<Sftp>,
1616
}
1717

18+
#[derive(Debug, Clone)]
19+
pub struct ServerStats {
20+
pub cpu_usage: String,
21+
pub memory_usage: String,
22+
pub disk_usage: String,
23+
}
1824
impl SSHConnection {
1925
pub fn new(hostname: &str, username: &str, password: &str, port: u16) -> Self {
2026
Self {
@@ -214,4 +220,67 @@ impl SSHConnection {
214220
Err("SFTP subsystem not initialized.".to_string())
215221
}
216222
}
223+
224+
fn run_command(session: &Session, cmd: &str) -> Result<String, String> {
225+
let mut channel = session
226+
.channel_session()
227+
.map_err(|e| format!("Failed to open channel: {}", e))?;
228+
channel
229+
.exec(cmd)
230+
.map_err(|e| format!("Failed to exec command {}: {}", cmd, e))?;
231+
232+
let mut stdout = String::new();
233+
channel
234+
.read_to_string(&mut stdout)
235+
.map_err(|e| format!("Failed to read command output: {}", e))?;
236+
237+
channel
238+
.wait_close()
239+
.map_err(|e| format!("Failed to close channel: {}", e))?;
240+
241+
Ok(stdout)
242+
}
243+
244+
pub fn fetch_stats(&self) -> Result<ServerStats, String> {
245+
let session = self
246+
.session
247+
.as_ref()
248+
.ok_or_else(|| "Session not initialized.".to_string())?;
249+
250+
let cpu_cmd = r#"top -bn1 | grep "Cpu(s)""#;
251+
let mem_cmd = r#"free -h | grep "Mem:""#;
252+
let disk_cmd = r#"df -h / | tail -1"#;
253+
254+
let raw_cpu = Self::run_command(session, cpu_cmd)?;
255+
let raw_mem = Self::run_command(session, mem_cmd)?;
256+
let raw_disk = Self::run_command(session, disk_cmd)?;
257+
258+
Ok(Self::process_stats(&raw_cpu, &raw_mem, &raw_disk))
259+
}
260+
261+
fn process_stats(raw_cpu: &str, raw_mem: &str, raw_disk: &str) -> ServerStats {
262+
let cpu_parts: Vec<&str> = raw_cpu.split_whitespace().collect();
263+
let cpu_usage = format!(
264+
"User: {}%, System: {}%, Idle: {}%, Steal: {}%",
265+
cpu_parts[1], cpu_parts[3], cpu_parts[7], cpu_parts[15]
266+
);
267+
268+
let mem_parts: Vec<&str> = raw_mem.split_whitespace().collect();
269+
let memory_usage = format!(
270+
"Total: {}, Used: {}, Free: {}, Buffers/Cache: {}",
271+
mem_parts[1], mem_parts[2], mem_parts[3], mem_parts[5]
272+
);
273+
274+
let disk_parts: Vec<&str> = raw_disk.split_whitespace().collect();
275+
let disk_usage = format!(
276+
"Filesystem: {}, Total: {}, Used: {}, Available: {}, Usage: {}",
277+
disk_parts[0], disk_parts[1], disk_parts[2], disk_parts[3], disk_parts[4]
278+
);
279+
280+
ServerStats {
281+
cpu_usage,
282+
memory_usage,
283+
disk_usage,
284+
}
285+
}
217286
}

0 commit comments

Comments
 (0)