topic/rust #2
|
@ -1,6 +1,2 @@
|
||||||
.idea/
|
/target
|
||||||
node_modules/
|
/.idea
|
||||||
out/
|
|
||||||
|
|
||||||
# Random test file...
|
|
||||||
0
|
|
|
@ -0,0 +1,298 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
"terminal_size",
|
||||||
|
"unicase",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kr"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.150"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.39"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "terminal_size"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
|
||||||
|
dependencies = [
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "kr"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.4.8", features = ["derive", "unicode", "wrap_help"] }
|
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
"name": "kr",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"bin": "src/index.js",
|
|
||||||
"main": "src/index.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "pkg package.json",
|
|
||||||
"copy-local": "cp -f out/kr-linux ~/bin/kr",
|
|
||||||
"build-local": "npm run build && npm run copy-local"
|
|
||||||
},
|
|
||||||
"pkg": {
|
|
||||||
"scripts": "src/**/*.js",
|
|
||||||
"targets": [
|
|
||||||
"node18-linux-x64",
|
|
||||||
"node18-macos-x64",
|
|
||||||
"node18-win-x64"
|
|
||||||
],
|
|
||||||
"outputPath": "out"
|
|
||||||
},
|
|
||||||
"author": "Ian Wijma",
|
|
||||||
"dependencies": {
|
|
||||||
"pkg": "^5.8.1",
|
|
||||||
"yargs": "^17.7.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^20.8.10",
|
|
||||||
"@types/yargs": "^17.0.29"
|
|
||||||
}
|
|
||||||
}
|
|
123
src/index.js
123
src/index.js
|
@ -1,123 +0,0 @@
|
||||||
const Yargs = require('yargs');
|
|
||||||
const {spawn} = require("child_process");
|
|
||||||
|
|
||||||
const yargs = Yargs(process.argv.splice(2))
|
|
||||||
.scriptName('kr')
|
|
||||||
.usage('kr [args] <process-to-run>')
|
|
||||||
.help()
|
|
||||||
.option('_rpm', {
|
|
||||||
default: 0,
|
|
||||||
description: 'The amount of Retries Per Minute, before we stop retrying',
|
|
||||||
type: 'number'
|
|
||||||
})
|
|
||||||
.option('_rph', {
|
|
||||||
default: 0,
|
|
||||||
description: 'The amount of Retries Per Hour, before we stop retrying',
|
|
||||||
type: 'number'
|
|
||||||
})
|
|
||||||
.option('_delay', {
|
|
||||||
default: 0,
|
|
||||||
description: 'Time in seconds we want to delay the restart with.',
|
|
||||||
type: 'number'
|
|
||||||
})
|
|
||||||
|
|
||||||
const { _ = [], _rpm: rpm, _rph: rph, _delay: delay } = yargs.argv;
|
|
||||||
const [command, ...args ] = _;
|
|
||||||
|
|
||||||
if (!command) {
|
|
||||||
return yargs.showHelp();
|
|
||||||
}
|
|
||||||
|
|
||||||
const SECONDS_IN_A_MINUTE = 60;
|
|
||||||
const SECONDS_IN_A_HOUR = 60 * 60;
|
|
||||||
|
|
||||||
let historyMax = 4;
|
|
||||||
let seconds = SECONDS_IN_A_MINUTE;
|
|
||||||
let restartName = 'minute';
|
|
||||||
|
|
||||||
if (rpm && rph) {
|
|
||||||
return console.error('Currently, can not define both --rpm and --rph, please choose only one.');
|
|
||||||
} else if (rpm) {
|
|
||||||
historyMax = rpm
|
|
||||||
} else if (rph) {
|
|
||||||
historyMax = rph
|
|
||||||
seconds = SECONDS_IN_A_HOUR
|
|
||||||
restartName = 'hour'
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {Object<number, string>} */
|
|
||||||
const history = {};
|
|
||||||
|
|
||||||
const getNow = () => Math.ceil(Date.now() / 1000); // Time in seconds
|
|
||||||
|
|
||||||
/** @param {string} logs */
|
|
||||||
const pushHistory = (logs) => history[getNow() + seconds] = logs;
|
|
||||||
|
|
||||||
const updateHistory = () => {
|
|
||||||
const now = getNow();
|
|
||||||
const clearKeys = Object.keys(history)
|
|
||||||
.filter((time) => time <= now);
|
|
||||||
|
|
||||||
clearKeys.forEach((key) => delete history[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkHistory = () => Object.keys(history).length <= historyMax;
|
|
||||||
|
|
||||||
const restart = () => setTimeout(() => runCommand(delay), delay * 1000);
|
|
||||||
|
|
||||||
const spawnCommand = () => {
|
|
||||||
const [ spawnCommand, ...cmdArgs ] = command.split(' ');
|
|
||||||
const spawnArgs = [...cmdArgs, ...args];
|
|
||||||
|
|
||||||
return spawn(spawnCommand, spawnArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
const runCommand = () => {
|
|
||||||
const runner = spawnCommand();
|
|
||||||
|
|
||||||
const commandLogs = [];
|
|
||||||
|
|
||||||
const pushLog = (logEntry) => commandLogs.push(logEntry);
|
|
||||||
|
|
||||||
const trimLog = () => {
|
|
||||||
if(commandLogs.length > 5000) commandLogs.shift()
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearLogs = () => commandLogs.length = 0;
|
|
||||||
|
|
||||||
const getLogs = () => commandLogs.join('\n');
|
|
||||||
|
|
||||||
const handleOut = (type, message) => {
|
|
||||||
pushLog(`[${type}]\t${message}`);
|
|
||||||
trimLog();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleExit = (exitCode) => {
|
|
||||||
if (exitCode === 0) {
|
|
||||||
console.log(`Exit code: ${exitCode}`);
|
|
||||||
} else{
|
|
||||||
console.log(`[CRASH] exit code: ${exitCode}`)
|
|
||||||
pushHistory(getLogs());
|
|
||||||
clearLogs();
|
|
||||||
updateHistory();
|
|
||||||
if (checkHistory()) {
|
|
||||||
console.log('Restarting...');
|
|
||||||
restart();
|
|
||||||
} else {
|
|
||||||
console.error(`The process crashed more then ${historyMax} times in the past ${restartName}, stop retrying.`);
|
|
||||||
console.error(`See below the last crash log:`);
|
|
||||||
const keys = Object.keys(history);
|
|
||||||
const lastKey = keys[keys.length-1];
|
|
||||||
console.log(history[lastKey]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
runner.on('close', (exitCode) => handleExit(exitCode))
|
|
||||||
runner.stdout.on('data', (data) => console.log(data.toString().trim()))
|
|
||||||
runner.stdout.on('data', (data) => handleOut('LOG', data.toString().trim()))
|
|
||||||
runner.stderr.on('data', (data) => handleOut('ERR', data.toString().trim()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leggo!~
|
|
||||||
runCommand();
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
use std::process::{Child, Command};
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
use clap::{arg, Parser};
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
struct Arguments {
|
||||||
|
// The amount of times we retry in a span of a minute, before we stop retrying
|
||||||
|
#[arg(long, default_value_t = 0, conflicts_with = "per_hour")]
|
||||||
|
per_minute: u8,
|
||||||
|
// The amount of times we retry in a span of a hour, before we stop retrying
|
||||||
|
#[arg(long, default_value_t = 0, conflicts_with = "per_minute")]
|
||||||
|
per_hour: u8,
|
||||||
|
// The amount of seconds we want to delay the restart with.
|
||||||
|
#[arg(long, default_value_t = 0)]
|
||||||
|
delay: u8,
|
||||||
|
|
||||||
|
#[arg()]
|
||||||
|
command: String
|
||||||
|
}
|
||||||
|
|
||||||
|
const SECONDS_IN_A_MINUTE: u16 = 60;
|
||||||
|
const SECONDS_IN_A_HOUR: u16 = 60 * 60;
|
||||||
|
|
||||||
|
struct Retry {
|
||||||
|
command: String,
|
||||||
|
history: Vec<u64>,
|
||||||
|
max_retries: u8,
|
||||||
|
timespan: u16,
|
||||||
|
restart_delay: u8,
|
||||||
|
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(),
|
||||||
|
};
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
run_command(&mut retry)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_now() -> u64 {
|
||||||
|
return SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_history(retry: &mut Retry) {
|
||||||
|
retry.history.push(get_now() + u64::from(retry.timespan));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_history(retry: &mut Retry) {
|
||||||
|
let now = get_now();
|
||||||
|
let clear_times: Vec<u64> = retry
|
||||||
|
.history
|
||||||
|
.iter()
|
||||||
|
.filter(|&time| time <= &now)
|
||||||
|
.map(|&time| time)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for time in clear_times {
|
||||||
|
retry.history.retain(|&h| h != time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_history(retry: &Retry) -> bool {
|
||||||
|
return retry.history.len().lt(&usize::from(retry.max_retries))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_process(retry: &Retry) -> std::io::Result<Child> {
|
||||||
|
let mut command_parts: Vec<String> = retry
|
||||||
|
.command
|
||||||
|
.split_whitespace()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut command: Command = Command::new(&command_parts[0]);
|
||||||
|
command_parts.remove(0);
|
||||||
|
command.args(command_parts);
|
||||||
|
|
||||||
|
return command.spawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_command(retry: &mut Retry) {
|
||||||
|
let mut process = spawn_process(retry)
|
||||||
|
.expect("Process failed on startup");
|
||||||
|
|
||||||
|
let exit_code = match process.wait() {
|
||||||
|
Ok(exit_code) => exit_code,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Failed to wait for process: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if exit_code.success() {
|
||||||
|
println!("Exit code: {}", exit_code);
|
||||||
|
} else {
|
||||||
|
println!("[CRASH] exit code: {}", exit_code);
|
||||||
|
push_history(retry);
|
||||||
|
update_history(retry);
|
||||||
|
if check_history(retry) {
|
||||||
|
println!("Restarting...");
|
||||||
|
restart(retry);
|
||||||
|
} else {
|
||||||
|
print!("The process has crashed more then {} times in the past {}, stop restarting", retry.max_retries, retry.restart_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restart(retry: &mut Retry) {
|
||||||
|
sleep(Duration::from_secs(u64::from(retry.restart_delay)));
|
||||||
|
|
||||||
|
run_command(retry);
|
||||||
|
}
|
Loading…
Reference in New Issue