Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
Ian Wijma | e3623f4ecc | |
Ian Wijma | 806d17328c | |
Ian Wijma | ef1e2c56c0 | |
Ian Wijma | 5c19c27136 | |
Ian Wijma | aad5010257 | |
Ian Wijma | ffa6d18e5e | |
Ian Wijma | 049a75e300 | |
Ian Wijma | dcf83a351f | |
Ian Wijma | 66ab232c9d | |
Ian Wijma | 99947dbefd | |
Ian Wijma | df5776e76d | |
Ian Wijma | 563938e51a | |
Ian Wijma | 8e6950270e |
|
@ -1,11 +1,12 @@
|
|||
name: Releasing
|
||||
run-name: ${{ gitea.actor }} is building a release releasing 🚀
|
||||
run-name: ${{ github.actor }} is building the files for a release 🚀
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: release ${{ matrix.target }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
/target
|
||||
/.idea
|
||||
/.idea
|
||||
|
|
|
@ -123,7 +123,7 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
|||
|
||||
[[package]]
|
||||
name = "kr"
|
||||
version = "1.0.0"
|
||||
version = "1.0.3"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "kr"
|
||||
version = "1.0.0"
|
||||
version = "1.0.3"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
@ -13,4 +13,3 @@ strip = true # Automatically strip symbols from the binary.
|
|||
opt-level = "z" # Optimize for size.
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 119 KiB |
|
@ -0,0 +1,35 @@
|
|||
Keep Running
|
||||
---
|
||||
|
||||
Keep running is a quick and easy way to **keep** a process **running** during development or other **non-production** tasks.
|
||||
|
||||
> Please for the love of sanity, do not use this is production...
|
||||
|
||||
# Usage
|
||||
|
||||
Below you will see the output of the `--help` command.
|
||||
Do note that if you don't specify any `--per-*` flag, it defaults to `--per-minute=4`.
|
||||
|
||||
```
|
||||
Usage: kr [OPTIONS] <COMMAND>
|
||||
|
||||
Arguments:
|
||||
<COMMAND>
|
||||
|
||||
Options:
|
||||
--per-minute <PER_MINUTE> [default: 0]
|
||||
--per-hour <PER_HOUR> [default: 0]
|
||||
--delay <DELAY> [default: 0]
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
```
|
||||
|
||||
# Use cases
|
||||
|
||||
## Game servers
|
||||
|
||||
/keep-running/ is a great tool to run, for example, a Modded minecraft server.
|
||||
As it automatically restarts the server if a crash occurs.
|
||||
|
||||
![img.png](assets/vault-hunters-3rd.png)
|
||||
|
81
src/main.rs
81
src/main.rs
|
@ -17,7 +17,7 @@ struct Arguments {
|
|||
delay: u8,
|
||||
|
||||
#[arg()]
|
||||
command: String
|
||||
command: String,
|
||||
}
|
||||
|
||||
const SECONDS_IN_A_MINUTE: u16 = 60;
|
||||
|
@ -29,30 +29,36 @@ struct Retry {
|
|||
max_retries: u8,
|
||||
timespan: u16,
|
||||
restart_delay: u8,
|
||||
restart_name: String
|
||||
restart_name: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let arguments = Arguments::parse();
|
||||
|
||||
let mut retry: Retry = Retry {
|
||||
command: arguments.command,
|
||||
history: Vec::new(),
|
||||
max_retries: 4,
|
||||
timespan: SECONDS_IN_A_MINUTE,
|
||||
restart_delay: arguments.delay,
|
||||
restart_name: "minute".to_string(),
|
||||
};
|
||||
let mut max_retries = 4;
|
||||
let mut timespan = SECONDS_IN_A_MINUTE;
|
||||
let mut restart_name = String::from("minute");
|
||||
|
||||
if arguments.per_minute > 0 {
|
||||
retry.max_retries = arguments.per_minute;
|
||||
} else if arguments.per_hour > 0 {
|
||||
retry.max_retries = arguments.per_hour;
|
||||
retry.timespan = SECONDS_IN_A_HOUR;
|
||||
retry.restart_name = "hour".to_string();
|
||||
let Arguments { per_minute, per_hour, .. } = arguments;
|
||||
if per_minute > 0 {
|
||||
max_retries = per_minute;
|
||||
} else if per_hour > 0 {
|
||||
max_retries = per_hour;
|
||||
timespan = SECONDS_IN_A_HOUR;
|
||||
restart_name = String::from("hour");
|
||||
}
|
||||
|
||||
run_command(&mut retry)
|
||||
let Arguments { command, delay: restart_delay, .. } = arguments;
|
||||
let retry: Retry = Retry {
|
||||
max_retries,
|
||||
timespan,
|
||||
restart_name,
|
||||
command,
|
||||
restart_delay,
|
||||
history: Vec::new(),
|
||||
};
|
||||
|
||||
run_command(retry)
|
||||
}
|
||||
|
||||
fn get_now() -> u64 {
|
||||
|
@ -62,29 +68,32 @@ fn get_now() -> u64 {
|
|||
.as_secs();
|
||||
}
|
||||
|
||||
fn push_history(retry: &mut Retry) {
|
||||
retry.history.push(get_now() + u64::from(retry.timespan));
|
||||
fn push_history(mut history: Vec<u64>, timespan: u16) -> Vec<u64> {
|
||||
history.push(get_now() + u64::from(timespan));
|
||||
|
||||
return history.to_owned()
|
||||
}
|
||||
|
||||
fn update_history(retry: &mut Retry) {
|
||||
fn update_history(mut history: Vec<u64>) -> Vec<u64> {
|
||||
let now = get_now();
|
||||
let clear_times: Vec<u64> = retry
|
||||
.history
|
||||
let clear_times: Vec<u64> = history
|
||||
.iter()
|
||||
.filter(|&time| time <= &now)
|
||||
.map(|&time| time)
|
||||
.collect();
|
||||
|
||||
for time in clear_times {
|
||||
retry.history.retain(|&h| h != time);
|
||||
history.retain(|&h| h != time);
|
||||
}
|
||||
|
||||
return history.to_owned();
|
||||
}
|
||||
|
||||
fn check_history(retry: &Retry) -> bool {
|
||||
return retry.history.len().lt(&usize::from(retry.max_retries))
|
||||
fn check_history(history: &Vec<u64>, max_retries: u8) -> bool {
|
||||
return history.len().lt(&usize::from(max_retries))
|
||||
}
|
||||
|
||||
fn spawn_process(retry: &Retry) -> std::io::Result<Child> {
|
||||
fn spawn_process(retry: &Retry) -> Result<Child, std::io::Error> {
|
||||
let mut command_parts: Vec<String> = retry
|
||||
.command
|
||||
.split_whitespace()
|
||||
|
@ -95,11 +104,14 @@ fn spawn_process(retry: &Retry) -> std::io::Result<Child> {
|
|||
command_parts.remove(0);
|
||||
command.args(command_parts);
|
||||
|
||||
return command.spawn();
|
||||
match command.spawn() {
|
||||
Ok(child) => Ok(child),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
fn run_command(retry: &mut Retry) {
|
||||
let mut process = spawn_process(retry)
|
||||
fn run_command(mut retry: Retry) {
|
||||
let mut process = spawn_process(&retry)
|
||||
.expect("Process failed on startup");
|
||||
|
||||
let exit_code = match process.wait() {
|
||||
|
@ -114,18 +126,19 @@ fn run_command(retry: &mut Retry) {
|
|||
println!("Exit code: {}", exit_code);
|
||||
} else {
|
||||
println!("[CRASH] exit code: {}", exit_code);
|
||||
push_history(retry);
|
||||
update_history(retry);
|
||||
if check_history(retry) {
|
||||
let pushed_history = push_history(retry.history, retry.timespan);
|
||||
let updated_history = update_history(pushed_history);
|
||||
if check_history(&updated_history, retry.max_retries) {
|
||||
retry.history = updated_history;
|
||||
println!("Restarting...");
|
||||
restart(retry);
|
||||
} else {
|
||||
print!("The process has crashed more then {} times in the past {}, stop restarting\n", retry.max_retries, retry.restart_name);
|
||||
println!("The process has crashed more than {} times in the past {}, stop restarting\n", retry.max_retries, retry.restart_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn restart(retry: &mut Retry) {
|
||||
fn restart(retry: Retry) {
|
||||
sleep(Duration::from_secs(u64::from(retry.restart_delay)));
|
||||
|
||||
run_command(retry);
|
||||
|
|
Loading…
Reference in New Issue