awesome_operates/helper/
execute.rs1use std::process::{Output, Stdio};
2
3use cfg_if::cfg_if;
4use serde::Serialize;
5use tokio::io::{AsyncBufReadExt, BufReader};
6use tokio::process::Command;
7use tokio::sync::mpsc::Sender;
8
9pub async fn execute_command(cmd: &str) -> anyhow::Result<Output> {
10 tracing::info!("execute command `{cmd}`");
11 Ok(Command::new("sh").args(["-c", cmd]).output().await?)
12}
13
14pub async fn execute_command_with_args_sender(cmd: &str, args: Vec<String>, tx: Sender<String>) {
15 tracing::info!("execute command `{cmd}` with args: `{args:?}`");
16 let mut child = Command::new(cmd)
17 .args(args)
18 .stdout(Stdio::piped())
19 .spawn()
20 .expect("fail to execute");
21
22 let stdout = child
23 .stdout
24 .take()
25 .expect("child did not have a handle to stdout");
26 let mut reader = BufReader::new(stdout).lines();
27
28 tokio::spawn(async move {
29 let status = child
30 .wait()
31 .await
32 .expect("child process encountered an error");
33
34 tracing::info!("child status was: {status}");
35 });
36
37 while let Some(line) = reader
38 .next_line()
39 .await
40 .unwrap_or(Some("fail to get output".to_owned()))
41 {
42 tx.send(line).await.unwrap();
43 }
44}
45
46pub async fn kill_process_by_pid<T>(pid: T)
56where
57 T: Serialize,
58{
59 let value = serde_json::json!(pid);
60 if value.as_u64().is_none() {
61 return;
62 }
63 let pid = value.to_string();
64 let pid_str = pid.as_str();
65 cfg_if! {
66 if #[cfg(unix)] {
67 let status = tokio::process::Command::new("kill")
68 .args(["-9", pid_str])
69 .status()
70 .await
71 .unwrap();
72 } else {
73 let status = tokio::process::Command::new("taskkill")
74 .args([r"/T", r"/F", r"/PID", pid_str])
75 .status()
76 .await
77 .unwrap();
78 }
79 }
80 tracing::info!("kill process {pid_str} with exit status {status:?}");
81}