tiny_native_scheduler/
lib.rs1use std::process::{Command, Output};
2
3type CustomResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
4
5pub fn execute_command_in_x_minutes(
28 command: &str,
29 minutes: i64,
30 #[allow(unused_variables)] win_task_name: &str,
31) -> CustomResult<Output> {
32 #[cfg(windows)]
33 let output = exec_in_x_minutes_win(command, minutes, win_task_name)?;
34 #[cfg(not(windows))]
35 let output = exec_in_x_minutes_unix(command, minutes)?;
36
37 Ok(output)
38}
39
40#[cfg(windows)]
41use time::{format_description, Duration, OffsetDateTime};
42
43#[cfg(windows)]
44fn exec_in_x_minutes_win(command: &str, minutes: i64, task_name: &str) -> CustomResult<Output> {
45 let scheduled_time = OffsetDateTime::now_local()? + Duration::minutes(minutes);
46 let format = format_description::parse("[hour]:[minute]")?;
47
48 let scheduled_time_string = scheduled_time.format(&format)?;
49
50 let output = Command::new("schtasks")
51 .args([
52 "/create",
53 "/tn",
54 task_name,
55 "/tr",
56 &format!("cmd /C start \"\" /MIN \"cmd\" \"/C {command}\""),
57 "/sc",
58 "once",
59 "/st",
60 &scheduled_time_string,
61 "/f",
62 ])
63 .output()?;
64
65 Ok(output)
66}
67
68#[cfg(not(windows))]
69use std::{
70 io::{Error, ErrorKind},
71 process::Stdio,
72};
73
74#[cfg(not(windows))]
75fn exec_in_x_minutes_unix(command: &str, minutes: i64) -> CustomResult<Output> {
76 let output = Command::new("echo")
77 .arg(command)
78 .stdout(Stdio::piped())
79 .spawn()?
80 .stdout
81 .ok_or_else(|| Error::new(ErrorKind::Other, "'at' failed to read from 'echo'"))?;
82
83 let output = Command::new("at")
84 .args(["now", "+", &minutes.to_string(), "minute"])
85 .stdin(Stdio::from(output))
86 .output()?;
87
88 Ok(output)
89}