Compare commits
11 Commits
main
...
multi-dock
Author | SHA1 | Date |
---|---|---|
Suyono | 3241350fe7 | |
Suyono | 88098e569c | |
Suyono | 0f822882f8 | |
Suyono | 838b884b8a | |
Suyono | 03c0c0401e | |
Suyono | d1c78f7b71 | |
Suyono | da71569517 | |
Suyono | 190479d796 | |
Suyono | 171c799a31 | |
Suyono | 11dbe7d4f0 | |
Suyono | d26cc87713 |
|
@ -27,6 +27,6 @@ rand = "0.8.5"
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
simplelog = "0.12.1"
|
simplelog = "0.12.1"
|
||||||
thiserror = "1.0.50"
|
thiserror = "1.0.50"
|
||||||
time = { version = "0.3.30", features = ["local-offset"]}
|
time = { version = "0.3.30", features = ["local-offset", "macros"]}
|
||||||
tokio = { version = "1.34.0", features = ["full"] }
|
tokio = { version = "1.34.0", features = ["full"] }
|
||||||
tokio-util = "0.7.10"
|
tokio-util = "0.7.10"
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
FROM rust:alpine as builder
|
||||||
|
|
||||||
|
ADD . /root/wingmate
|
||||||
|
|
||||||
|
WORKDIR /root/wingmate
|
||||||
|
|
||||||
|
RUN apk add musl-dev && cargo clean && \
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
|
||||||
|
COPY --from=builder /root/wingmate/target/release/wingmate-rs /usr/local/bin/wingmate
|
||||||
|
COPY --from=builder /root/wingmate/target/release/wmtest-helper-dummy /usr/local/bin/wmtest-helper-dummy
|
||||||
|
COPY --from=builder /root/wingmate/target/release/wmtest-helper-spawner /usr/local/bin/wmtest-helper-spawner
|
||||||
|
COPY --from=builder /root/wingmate/target/release/wmtest-helper-log /usr/local/bin/wmtest-helper-log
|
||||||
|
|
||||||
|
ADD docker/alpine/etc/ /etc/
|
||||||
|
ADD docker/alpine/entry.sh /usr/local/bin/entry.sh
|
||||||
|
|
||||||
|
RUN chmod -R ugo+x /etc/wingmate && chmod +x /usr/local/bin/entry.sh && apk add tzdata && \
|
||||||
|
ln -sv /usr/share/zoneinfo/Australia/Sydney /etc/localtime
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/usr/local/bin/entry.sh" ]
|
||||||
|
|
||||||
|
CMD [ "/usr/local/bin/wingmate" ]
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ $# -gt 0 ];then
|
||||||
|
exec "$@"
|
||||||
|
else
|
||||||
|
exec /usr/local/bin/wingmate
|
||||||
|
fi
|
|
@ -0,0 +1,4 @@
|
||||||
|
17 * * * * /etc/wingmate/crontab.d/cron1.sh
|
||||||
|
*/5 * * * * /etc/wingmate/crontab.d/cron2.sh
|
||||||
|
21,41 3,6,14,17,20,22 * * * /etc/wingmate/crontab.d/cron3.sh
|
||||||
|
* * * * * /etc/wingmate/crontab.d/cron4.sh
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec wmtest-helper-log /var/log/cron1.log "this cron runs every hour on minute 17"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec wmtest-helper-log /var/log/cron2.log "this cron runs every hour on minute 5,10,15,20,25,30,35,40,45,50,55"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec wmtest-helper-log /var/log/cron3.log "this cron runs based on this specification: 21,41 3,6,14,17,20,22 * * *"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec wmtest-helper-log /var/log/cron4.log "this cron runs every minute"
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export LOG_PATH=/var/log/one.log
|
||||||
|
exec /usr/local/bin/wmtest-helper-spawner 10
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export LOG_PATH=/var/log/three.log
|
||||||
|
exec /usr/local/bin/wmtest-helper-spawner 13
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export LOG_PATH=/var/log/two.log
|
||||||
|
exec /usr/local/bin/wmtest-helper-spawner 4
|
|
@ -0,0 +1,9 @@
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
|
ADD target/debug/init /usr/local/bin/init
|
||||||
|
ADD docker/etc/ /etc/
|
||||||
|
|
||||||
|
RUN chmod ugo+x /etc/wingmate/services/one && chmod ugo+x /etc/wingmate/services/two.sh && \
|
||||||
|
chmod ugo-x /etc/wingmate/services/three.sh
|
||||||
|
|
||||||
|
CMD [ "/usr/local/bin/init" ]
|
|
@ -0,0 +1,3 @@
|
||||||
|
17 * * * * sleep 1
|
||||||
|
*/12 * * * * sleep 1
|
||||||
|
12,17,27 * * * * sleep 1
|
|
@ -0,0 +1 @@
|
||||||
|
you cannot run this file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
exec sleep 1
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
exec sleep 1
|
|
@ -15,25 +15,25 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
let log_path = env::var("LOG_PATH")?;
|
let log_path = env::var("LOG_PATH")?;
|
||||||
let file = OpenOptions::new().append(true).create(true).open(log_path)?;
|
let file = OpenOptions::new().append(true).create(true).open(log_path)?;
|
||||||
WriteLogger::new(LevelFilter::Debug, Config::default(), file);
|
WriteLogger::init(LevelFilter::Debug, Config::default(), file)?;
|
||||||
|
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
let x: u64 = args[1].parse()?;
|
let x: u64 = args[1].parse()?;
|
||||||
loop {
|
for _i in 0..x {
|
||||||
for _i in 0..x {
|
let sleep_time = rng.gen_range(10..20);
|
||||||
let sleep_time = rng.gen_range(10..20);
|
info!("starting wmtest-helper-dummy {}", &sleep_time);
|
||||||
info!("starting wmtest-helper-dummy {}", &sleep_time);
|
let child = Command::new("/usr/local/bin/wmtest-helper-dummy").arg(format!("{}", sleep_time)).spawn();
|
||||||
let child = Command::new("/usr/local/bin/wmtest-helper-dummy").arg(format!("{}", sleep_time)).spawn();
|
if let Err(e) = child {
|
||||||
if let Err(e) = child {
|
error!("error spawning child: {e}");
|
||||||
error!("error spawning child: {e}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let pause_time = rng.gen_range(10..20);
|
|
||||||
info!("going to sleep for {}", &pause_time);
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(pause_time));
|
|
||||||
info!("waking up")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let pause_time = rng.gen_range(5..10);
|
||||||
|
info!("going to sleep for {}", &pause_time);
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(pause_time));
|
||||||
} else {
|
} else {
|
||||||
return Err(anyhow::anyhow!("invalid arguments").into());
|
return Err(anyhow::anyhow!("invalid arguments").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,6 @@ pub async fn start() -> Result<(), error::WingmateInitError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = config::Config::find(vec_search)?;
|
let config = config::Config::find(vec_search)?;
|
||||||
dbg!(&config);
|
// dbg!(&config);
|
||||||
daemon::start(config).await
|
daemon::start(config).await
|
||||||
}
|
}
|
|
@ -1,21 +1,24 @@
|
||||||
|
use time::error::IndeterminateOffset;
|
||||||
use tokio::task::JoinSet;
|
use tokio::task::JoinSet;
|
||||||
use tokio::process::{Command, Child};
|
use tokio::process::{Command, Child};
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tokio::io::Result as tokio_result;
|
use tokio::io::Result as tokio_result;
|
||||||
use tokio::time::{sleep, interval};
|
use tokio::time::{sleep, interval};
|
||||||
|
use std::env;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
use nix::sys::signal::{kill, Signal};
|
use nix::sys::signal::{kill, Signal};
|
||||||
use nix::errno::Errno;
|
use nix::errno::Errno;
|
||||||
use nix::unistd::Pid;
|
use nix::unistd::Pid;
|
||||||
use anyhow::{Context, anyhow};
|
use anyhow::{Context, anyhow};
|
||||||
use time::{OffsetDateTime, Duration as TimeDur, Weekday};
|
use time::{OffsetDateTime, Duration as TimeDur, Weekday, UtcOffset};
|
||||||
use crate::init::config;
|
use crate::init::config;
|
||||||
use crate::init::error::{WingmateInitError, CronConfigError};
|
use crate::init::error::{WingmateInitError, CronConfigError};
|
||||||
|
|
||||||
|
|
||||||
const CRON_TRIGGER_WAIT_SECS: u64 = 20;
|
const CRON_TRIGGER_WAIT_SECS: u64 = 20;
|
||||||
|
const ENV_UTC_OFFSET: &'static str = "WINGMATE_TIME_OFFSET";
|
||||||
|
|
||||||
pub fn start_services(ts: &mut JoinSet<Result<(), WingmateInitError>>, cfg: &config::Config, cancel: CancellationToken)
|
pub fn start_services(ts: &mut JoinSet<Result<(), WingmateInitError>>, cfg: &config::Config, cancel: CancellationToken)
|
||||||
-> Result<(), WingmateInitError> {
|
-> Result<(), WingmateInitError> {
|
||||||
|
@ -111,9 +114,11 @@ fn result_match(result: tokio_result<ExitStatus>) -> Result<(), anyhow::Error> {
|
||||||
pub fn start_cron(ts: &mut JoinSet<Result<(), WingmateInitError>>, cfg: &config::Config, cancel: CancellationToken)
|
pub fn start_cron(ts: &mut JoinSet<Result<(), WingmateInitError>>, cfg: &config::Config, cancel: CancellationToken)
|
||||||
-> Result<(), WingmateInitError> {
|
-> Result<(), WingmateInitError> {
|
||||||
|
|
||||||
|
dbg!("cron: starting");
|
||||||
for c_ in cfg.get_cron_iter() {
|
for c_ in cfg.get_cron_iter() {
|
||||||
let cron = c_.clone();
|
let cron = c_.clone();
|
||||||
let in_loop_cancel = cancel.clone();
|
let in_loop_cancel = cancel.clone();
|
||||||
|
dbg!("cron: item", c_);
|
||||||
|
|
||||||
ts.spawn(async move {
|
ts.spawn(async move {
|
||||||
if cron.day_of_month != config::CronTimeFieldSpec::Any
|
if cron.day_of_month != config::CronTimeFieldSpec::Any
|
||||||
|
@ -121,18 +126,35 @@ pub fn start_cron(ts: &mut JoinSet<Result<(), WingmateInitError>>, cfg: &config:
|
||||||
return Err(WingmateInitError::CronConfig { source: CronConfigError::ClashingConfig });
|
return Err(WingmateInitError::CronConfig { source: CronConfigError::ClashingConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
// let cron = cron.clone();
|
dbg!("cron: async task spawned");
|
||||||
|
|
||||||
|
let cron = cron.clone();
|
||||||
let mut cron_interval = interval(Duration::from_secs(CRON_TRIGGER_WAIT_SECS));
|
let mut cron_interval = interval(Duration::from_secs(CRON_TRIGGER_WAIT_SECS));
|
||||||
let mut cron_procs: JoinSet<Result<(), WingmateInitError>> = JoinSet::new();
|
let mut cron_procs: JoinSet<Result<(), WingmateInitError>> = JoinSet::new();
|
||||||
let mut last_running: Option<OffsetDateTime> = None;
|
let mut last_running: Option<OffsetDateTime> = None;
|
||||||
'continuous: loop {
|
'continuous: loop {
|
||||||
let cron = cron.clone();
|
let cron = cron.clone();
|
||||||
let cron_proc_cancel = in_loop_cancel.clone();
|
let cron_proc_cancel = in_loop_cancel.clone();
|
||||||
|
dbg!("cron: single: in loop", &cron.command);
|
||||||
|
|
||||||
let mut flag = true;
|
let mut flag = true;
|
||||||
|
|
||||||
if let Ok(local_time) = OffsetDateTime::now_local() {
|
let tr: Result<OffsetDateTime, IndeterminateOffset>;
|
||||||
|
if let Ok(offset) = env::var(ENV_UTC_OFFSET) {
|
||||||
|
if let Ok(i_off) = offset.parse::<i8>() {
|
||||||
|
let utc_time = OffsetDateTime::now_utc().to_offset(UtcOffset::from_hms(i_off, 0, 0).unwrap());
|
||||||
|
tr = Ok(utc_time);
|
||||||
|
} else {
|
||||||
|
tr = OffsetDateTime::now_local();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tr = OffsetDateTime::now_local();
|
||||||
|
}
|
||||||
|
// let tr = OffsetDateTime::now_local();
|
||||||
|
if let Ok(local_time) = tr {
|
||||||
|
dbg!("cron: current local time", &local_time);
|
||||||
if let Some(last) = last_running {
|
if let Some(last) = last_running {
|
||||||
|
dbg!("cron: last runing instance", &last);
|
||||||
if local_time - last < TimeDur::minutes(1) {
|
if local_time - last < TimeDur::minutes(1) {
|
||||||
flag = false;
|
flag = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -141,14 +163,25 @@ pub fn start_cron(ts: &mut JoinSet<Result<(), WingmateInitError>>, cfg: &config:
|
||||||
cron.day_of_month.is_match(local_time.day()) &&
|
cron.day_of_month.is_match(local_time.day()) &&
|
||||||
cron.day_of_week.is_match(weekday_map(local_time.weekday()));
|
cron.day_of_week.is_match(weekday_map(local_time.weekday()));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
flag = flag && cron.minute.is_match(local_time.minute()) &&
|
||||||
|
cron.hour.is_match(local_time.hour()) &&
|
||||||
|
cron.day_of_month.is_match(local_time.day()) &&
|
||||||
|
cron.day_of_week.is_match(weekday_map(local_time.weekday()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if flag {
|
if flag {
|
||||||
|
dbg!("cron: timing: hit: {}", &cron.command);
|
||||||
last_running = Some(local_time);
|
last_running = Some(local_time);
|
||||||
cron_procs.spawn(async move {
|
cron_procs.spawn(async move {
|
||||||
run_cron_command(cron.command.clone(), cron_proc_cancel).await
|
run_cron_command(cron.command.clone(), cron_proc_cancel).await
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dbg!("cron: unexpected error");
|
||||||
|
if let Err(e) = tr {
|
||||||
|
dbg!(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cron_procs.is_empty() {
|
if cron_procs.is_empty() {
|
||||||
|
@ -209,6 +242,7 @@ async fn run_cron_command(command: String, cancel: CancellationToken) -> Result<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbg!("cron: in running command");
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
return Err(WingmateInitError::Other { source: anyhow!("parsed as empty: {}", command) });
|
return Err(WingmateInitError::Other { source: anyhow!("parsed as empty: {}", command) });
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue