Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a0cb6d272 | |||
| 77c06befda | |||
| 638e05a13a | |||
| eaa55c69b4 | |||
| 03eb96661e | |||
| baa3b60ef3 | |||
| 2d1f10cd26 | |||
| 231051bd8f | |||
| 67eea6f149 | |||
| ff7f95e1bb | |||
| 0682019085 | |||
| e2b7d93035 | |||
| 43929736ca | |||
| f0e0bf4db8 | |||
| bd12ee9e49 | |||
| 6f77993798 | |||
| bfa68743da | |||
| dbd73958cf |
@@ -1,8 +1,8 @@
|
||||
# This file is machine-generated - editing it directly is not advised
|
||||
|
||||
julia_version = "1.12.1"
|
||||
julia_version = "1.12.5"
|
||||
manifest_format = "2.0"
|
||||
project_hash = "324e0aa322681a327b337bcd7a8530af39c981d0"
|
||||
project_hash = "b869f60c186657e1a66a3bb09e6f25647cba4a4b"
|
||||
|
||||
[[deps.Artifacts]]
|
||||
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
|
||||
@@ -25,9 +25,9 @@ version = "0.7.8"
|
||||
|
||||
[[deps.ConcurrentUtilities]]
|
||||
deps = ["Serialization", "Sockets"]
|
||||
git-tree-sha1 = "d9d26935a0bcffc87d2613ce14c527c99fc543fd"
|
||||
git-tree-sha1 = "21d088c496ea22914fe80906eb5bce65755e5ec8"
|
||||
uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb"
|
||||
version = "2.5.0"
|
||||
version = "2.5.1"
|
||||
|
||||
[[deps.Dates]]
|
||||
deps = ["Printf"]
|
||||
@@ -42,9 +42,9 @@ version = "0.1.11"
|
||||
|
||||
[[deps.HTTP]]
|
||||
deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "PrecompileTools", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"]
|
||||
git-tree-sha1 = "5e6fe50ae7f23d171f44e311c2960294aaa0beb5"
|
||||
git-tree-sha1 = "51059d23c8bb67911a2e6fd5130229113735fc7e"
|
||||
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
||||
version = "1.10.19"
|
||||
version = "1.11.0"
|
||||
|
||||
[[deps.InteractiveUtils]]
|
||||
deps = ["Markdown"]
|
||||
@@ -59,9 +59,9 @@ version = "1.7.1"
|
||||
|
||||
[[deps.JSON]]
|
||||
deps = ["Dates", "Logging", "Parsers", "PrecompileTools", "StructUtils", "UUIDs", "Unicode"]
|
||||
git-tree-sha1 = "eb04df293213df64ddd720c86de3c431f5f8ccf1"
|
||||
git-tree-sha1 = "b3ad4a0255688dcb895a52fafbaae3023b588a90"
|
||||
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
version = "1.2.1"
|
||||
version = "1.4.0"
|
||||
|
||||
[deps.JSON.extensions]
|
||||
JSONArrowExt = ["ArrowTypes"]
|
||||
@@ -95,19 +95,19 @@ version = "1.11.0"
|
||||
|
||||
[[deps.MbedTLS]]
|
||||
deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"]
|
||||
git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf"
|
||||
git-tree-sha1 = "8785729fa736197687541f7053f6d8ab7fc44f92"
|
||||
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
|
||||
version = "1.1.9"
|
||||
version = "1.1.10"
|
||||
|
||||
[[deps.MbedTLS_jll]]
|
||||
deps = ["Artifacts", "JLLWrappers", "Libdl"]
|
||||
git-tree-sha1 = "3cce3511ca2c6f87b19c34ffc623417ed2798cbd"
|
||||
git-tree-sha1 = "ff69a2b1330bcb730b9ac1ab7dd680176f5896b8"
|
||||
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
|
||||
version = "2.28.10+0"
|
||||
version = "2.28.1010+0"
|
||||
|
||||
[[deps.MozillaCACerts_jll]]
|
||||
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
|
||||
version = "2025.5.20"
|
||||
version = "2025.11.4"
|
||||
|
||||
[[deps.NetworkOptions]]
|
||||
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
|
||||
@@ -115,14 +115,14 @@ version = "1.3.0"
|
||||
|
||||
[[deps.OpenSSL]]
|
||||
deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "NetworkOptions", "OpenSSL_jll", "Sockets"]
|
||||
git-tree-sha1 = "386b47442468acfb1add94bf2d85365dea10cbab"
|
||||
git-tree-sha1 = "1d1aaa7d449b58415f97d2839c318b70ffb525a0"
|
||||
uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c"
|
||||
version = "1.6.0"
|
||||
version = "1.6.1"
|
||||
|
||||
[[deps.OpenSSL_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
|
||||
version = "3.5.1+0"
|
||||
version = "3.5.4+0"
|
||||
|
||||
[[deps.Parsers]]
|
||||
deps = ["Dates", "PrecompileTools", "UUIDs"]
|
||||
@@ -138,9 +138,9 @@ version = "1.3.3"
|
||||
|
||||
[[deps.Preferences]]
|
||||
deps = ["TOML"]
|
||||
git-tree-sha1 = "0f27480397253da18fe2c12a4ba4eb9eb208bf3d"
|
||||
git-tree-sha1 = "8b770b60760d4451834fe79dd483e318eee709c4"
|
||||
uuid = "21216c6a-2e73-6563-6e65-726566657250"
|
||||
version = "1.5.0"
|
||||
version = "1.5.2"
|
||||
|
||||
[[deps.Printf]]
|
||||
deps = ["Unicode"]
|
||||
@@ -171,16 +171,18 @@ version = "1.11.0"
|
||||
|
||||
[[deps.StructUtils]]
|
||||
deps = ["Dates", "UUIDs"]
|
||||
git-tree-sha1 = "79529b493a44927dd5b13dde1c7ce957c2d049e4"
|
||||
git-tree-sha1 = "fa95b3b097bcef5845c142ea2e085f1b2591e92c"
|
||||
uuid = "ec057cc2-7a8d-4b58-b3b3-92acb9f63b42"
|
||||
version = "2.6.0"
|
||||
version = "2.7.1"
|
||||
|
||||
[deps.StructUtils.extensions]
|
||||
StructUtilsMeasurementsExt = ["Measurements"]
|
||||
StructUtilsStaticArraysCoreExt = ["StaticArraysCore"]
|
||||
StructUtilsTablesExt = ["Tables"]
|
||||
|
||||
[deps.StructUtils.weakdeps]
|
||||
Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
|
||||
StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
|
||||
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
||||
|
||||
[[deps.StyledStrings]]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
[deps]
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
||||
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
|
||||
@@ -29,11 +29,11 @@ Both scripts run continuously in the background, performing periodic health chec
|
||||
```julia
|
||||
const ROUTER_IP = "192.168.88.1" # Target router IP address
|
||||
const TIMEOUT_SECS = 30 # Request timeout in seconds
|
||||
const ATTEMPTS_PER_CHECK = 3 # Number of ping attempts per check
|
||||
const BACKOFF_BETWEEN_ATTEMPTS = 60 # Seconds between retry attempts
|
||||
const ATTEMPTS_PER_CHECK = 1 # Number of ping attempts per check
|
||||
const BACKOFF_BETWEEN_ATTEMPTS = 1 # Seconds between retry attempts
|
||||
const FAILS_TO_REBOOT = 3 # Consecutive failures before reboot
|
||||
const COOLDOWN_AFTER_REBOOT_SECS = 600 # Minimum seconds between reboots
|
||||
const DRY_RUN = true # Set false to enable actual reboots
|
||||
const DRY_RUN = false # Set false to enable actual reboots
|
||||
const CHECK_INTERVAL_SECS = 60 # Check interval in seconds
|
||||
```
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"last_reboot_datetime":"2026-01-31T12:56:40.834","consecutive_fails":0}
|
||||
{"last_reboot_datetime":"2026-03-20T15:23:19.868","consecutive_fails":2}
|
||||
@@ -7,26 +7,33 @@
|
||||
# ------------------------------------------------------------------------------------------------ #
|
||||
# add the following to root's crontab (sudo crontab -e) #
|
||||
# ------------------------------------------------------------------------------------------------ #
|
||||
# *** juliar is root's julia (sudo crontab -e) but I symlinked to juliar because I want to seperate it from user's julia
|
||||
# @reboot /usr/local/bin/juliar /home/ton/docker-programs/check_and_reboot/check_router_reboot.jl >> /var/log/check_reboot.log 2>&1
|
||||
# @reboot /root/.juliaup/bin/julia /root/docker-apps/check_and_reboot/check_router_reboot.jl >> /var/log/check_reboot.log 2>&1
|
||||
|
||||
# ---------------- For PC that has juliar for root user and julia for normal user ---------------- #
|
||||
# linux_prompt> @reboot sleep 30 && /usr/local/bin/juliar /home/ton/docker-programs/check_and_reboot/check_router_reboot.jl >> /var/log/check_reboot.log 2>&1
|
||||
# *** juliar is julia that I install separately for root user (sudo crontab -e) which I symlinked to juliar because I want to separate it from user's julia
|
||||
|
||||
# ---------------------------------- For PC that has only julia ---------------------------------- #
|
||||
# linux_prompt> @reboot sleep 30 && /root/.juliaup/bin/julia /root/docker-apps/check_and_reboot/check_router_reboot.jl >> /var/log/check_reboot.log 2>&1
|
||||
|
||||
|
||||
|
||||
using Dates, Printf, JSON
|
||||
|
||||
# Configuration
|
||||
const ROUTER_IP = "192.168.88.1"
|
||||
const TIMEOUT_SECS = 30 # request timeout
|
||||
const ATTEMPTS_PER_CHECK = 3 # number of ping attempts per check
|
||||
const BACKOFF_BETWEEN_ATTEMPTS = 60 # seconds between attempts
|
||||
const ATTEMPTS_PER_CHECK = 1 # number of ping attempts per check
|
||||
const BACKOFF_BETWEEN_ATTEMPTS = 1 # seconds between ping attempts
|
||||
const FAILS_TO_REBOOT = 3 # consecutive failed checks required to trigger reboot
|
||||
const COOLDOWN_AFTER_REBOOT_SECS = 600 # do not reboot again within this many seconds
|
||||
const COOLDOWN_AFTER_REBOOT_SECS = 300 # do not reboot again within this many seconds
|
||||
const DRY_RUN = false # set false to actually reboot
|
||||
const CHECK_INTERVAL_SECS = 60 # run a check every CHECK_INTERVAL_SECS seconds
|
||||
|
||||
const thisFolderPath = @__DIR__
|
||||
const thisFilePath = @__FILE__
|
||||
const LogFilePath = "$thisFolderPath/check_router_reboot_log.txt" # write logs here and also broadcast
|
||||
const StateFilePath = "$thisFolderPath/check_and_reboot_state.json"
|
||||
|
||||
# println(0)
|
||||
# Simple broadcast helper
|
||||
# Simple broadcast helper (safe Cmd construction)
|
||||
function broadcast_msg(msg::AbstractString)
|
||||
@@ -120,6 +127,7 @@ function load_state(StateFilePath)
|
||||
return State(cf, DateTime(lr))
|
||||
end
|
||||
catch e
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Warning loading state: $e")
|
||||
end
|
||||
return State(0, nothing)
|
||||
@@ -128,7 +136,6 @@ end
|
||||
function save_state(st::State, StateFilePath)
|
||||
obj = Dict("consecutive_fails" => st.consecutive_fails,
|
||||
"last_reboot_datetime" => st.last_reboot_datetime)
|
||||
@show StateFilePath
|
||||
JSON.json(StateFilePath, obj)
|
||||
end
|
||||
|
||||
@@ -157,18 +164,40 @@ function check_router_once(ip::AbstractString; timeout=TIMEOUT_SECS)
|
||||
end
|
||||
end
|
||||
|
||||
# Check if running as root
|
||||
function is_root()::Bool
|
||||
try
|
||||
result = read(`whoami`, String)
|
||||
return strip(result) == "root"
|
||||
catch
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Reboot command selection
|
||||
# Return program and separate args as plain strings
|
||||
function reboot_command()
|
||||
if Sys.iswindows()
|
||||
return ("/usr/bin/cmd", "/C", "shutdown /r /t 0")
|
||||
elseif Sys.isapple()
|
||||
return ("/usr/bin/sudo", "shutdown", "-r", "now")
|
||||
elseif Sys.islinux()
|
||||
if isfile("/bin/systemctl") || isfile("/usr/bin/systemctl")
|
||||
return ("/usr/bin/sudo", "systemctl", "reboot")
|
||||
if is_root()
|
||||
return ("/sbin/reboot")
|
||||
else
|
||||
return ("/usr/bin/sudo", "reboot")
|
||||
return ("/usr/bin/sudo", "shutdown", "-r", "now")
|
||||
end
|
||||
elseif Sys.islinux()
|
||||
if is_root()
|
||||
if isfile("/bin/systemctl")
|
||||
return ("/bin/systemctl", "reboot")
|
||||
else
|
||||
return ("/usr/sbin/reboot")
|
||||
end
|
||||
else
|
||||
if isfile("/bin/systemctl") || isfile("/usr/bin/systemctl")
|
||||
return ("/usr/bin/sudo", "systemctl", "reboot")
|
||||
else
|
||||
return ("/usr/bin/sudo", "reboot")
|
||||
end
|
||||
end
|
||||
else
|
||||
return nothing
|
||||
@@ -178,6 +207,7 @@ end
|
||||
function do_reboot()
|
||||
cmd = reboot_command()
|
||||
if cmd === nothing
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Reboot not supported on this OS")
|
||||
return false
|
||||
end
|
||||
@@ -186,10 +216,11 @@ function do_reboot()
|
||||
cmd_str = join(map(x -> replace(x, '"' => "\\\""), cmd), " ")
|
||||
|
||||
if DRY_RUN
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("DRY RUN: would run reboot command: $cmd_str")
|
||||
return true
|
||||
end
|
||||
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Executing reboot command: $cmd_str")
|
||||
try
|
||||
# Construct a Cmd from an array so arguments are passed directly (no shell)
|
||||
@@ -197,6 +228,7 @@ function do_reboot()
|
||||
run(Cmd(cmd_array))
|
||||
return true
|
||||
catch e
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Failed to execute reboot command: $e")
|
||||
return false
|
||||
end
|
||||
@@ -205,69 +237,124 @@ end
|
||||
|
||||
# Single check iteration
|
||||
function perform_check!(st::State)
|
||||
if st.last_reboot_datetime !== nothing
|
||||
timepass = ((Dates.now() - st.last_reboot_datetime).value / 1000) |> floor |> Int
|
||||
# println(1)
|
||||
success = false
|
||||
last_result = nothing
|
||||
for i in 1:ATTEMPTS_PER_CHECK
|
||||
|
||||
if timepass < COOLDOWN_AFTER_REBOOT_SECS
|
||||
logmsg("In cooldown after recent reboot; skipping check. $timepass/$COOLDOWN_AFTER_REBOOT_SECS seconds")
|
||||
return
|
||||
# # for testing without actual ping
|
||||
# ok, result = values(JSON.parsefile("/home/ton/docker-programs/check_and_reboot/test_ping_result.json"))
|
||||
|
||||
ok, result = check_router_once(ROUTER_IP)
|
||||
|
||||
if ok
|
||||
success = true
|
||||
break
|
||||
end
|
||||
end
|
||||
success = false
|
||||
last_result = nothing
|
||||
for i in 1:ATTEMPTS_PER_CHECK
|
||||
ok, result = check_router_once(ROUTER_IP)
|
||||
last_result = result
|
||||
if ok
|
||||
success = true
|
||||
break
|
||||
end
|
||||
sleep(BACKOFF_BETWEEN_ATTEMPTS)
|
||||
end
|
||||
if success
|
||||
if st.consecutive_fails > 0
|
||||
logmsg("$ROUTER_IP is reachable; resetting consecutive failure counter.")
|
||||
else
|
||||
# logmsg("$ROUTER_IP is reachable.")
|
||||
end
|
||||
st.consecutive_fails = 0
|
||||
save_state(st, StateFilePath)
|
||||
return
|
||||
else
|
||||
st.consecutive_fails += 1
|
||||
routerresult = isnothing(last_result) ? "no response" : last_result
|
||||
logmsg("$ROUTER_IP is unreachable (last result: $routerresult). Consecutive fails: $(st.consecutive_fails)/$FAILS_TO_REBOOT.")
|
||||
save_state(st, StateFilePath)
|
||||
end
|
||||
if st.consecutive_fails >= FAILS_TO_REBOOT
|
||||
save_state(st, StateFilePath)
|
||||
ok = do_reboot()
|
||||
if ok
|
||||
thisFilePath = @__FILE__
|
||||
broadcast_msg("Broadcasting from file: $thisFilePath")
|
||||
logmsg("Reboot executed (or simulated). Resetting failure counter.")
|
||||
st.consecutive_fails = 0
|
||||
st.last_reboot_datetime = Dates.now()
|
||||
save_state(st, StateFilePath)
|
||||
else
|
||||
logmsg("Reboot attempt failed; will retry after next interval.")
|
||||
end
|
||||
end
|
||||
end
|
||||
sleep(BACKOFF_BETWEEN_ATTEMPTS)
|
||||
end
|
||||
routerresult = isnothing(last_result) ? "no response" : last_result
|
||||
|
||||
# Check if we're in cooldown period
|
||||
in_cooldown = false
|
||||
if st.last_reboot_datetime !== nothing
|
||||
timepass = ((Dates.now() - st.last_reboot_datetime).value / 1000) |> floor |> Int
|
||||
if timepass < COOLDOWN_AFTER_REBOOT_SECS
|
||||
in_cooldown = true
|
||||
end
|
||||
end
|
||||
# @show in_cooldown
|
||||
# println(2)
|
||||
if in_cooldown
|
||||
# println("2-1")
|
||||
# During cooldown, track failures but don't trigger reboot yet
|
||||
if success
|
||||
broadcast_msg("Broadcasting from file: $thisFilePath")
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("$ROUTER_IP is reachable during cooldown. Router is back online! Resetting state.")
|
||||
st.consecutive_fails = 0
|
||||
save_state(st, StateFilePath)
|
||||
else
|
||||
# println("2-2")
|
||||
st.consecutive_fails += 1
|
||||
broadcast_msg("Broadcasting from file: $thisFilePath")
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("$ROUTER_IP is unreachable during cooldown. Consecutive fails: $(st.consecutive_fails)/$FAILS_TO_REBOOT.")
|
||||
save_state(st, StateFilePath)
|
||||
end
|
||||
return
|
||||
end
|
||||
# println(3)
|
||||
# Outside cooldown - full check with potential reboot
|
||||
if success
|
||||
# println("3-1")
|
||||
if st.consecutive_fails > 0
|
||||
# println("3-2")
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("$ROUTER_IP is reachable; resetting consecutive failure counter.")
|
||||
else
|
||||
# logmsg("$ROUTER_IP is reachable.")
|
||||
end
|
||||
st.consecutive_fails = 0
|
||||
save_state(st, StateFilePath)
|
||||
return
|
||||
else
|
||||
st.consecutive_fails += 1
|
||||
broadcast_msg("Broadcasting from file: $thisFilePath")
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("$ROUTER_IP is unreachable (last result: $routerresult). Consecutive fails: $(st.consecutive_fails)/$FAILS_TO_REBOOT.")
|
||||
save_state(st, StateFilePath)
|
||||
end
|
||||
# println(4)
|
||||
if st.consecutive_fails >= FAILS_TO_REBOOT
|
||||
# println("4-1")
|
||||
save_state(st, StateFilePath)
|
||||
ok = do_reboot()
|
||||
if ok
|
||||
# println("4-2")
|
||||
broadcast_msg("Broadcasting from file: $thisFilePath")
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Reboot executed (or simulated). Resetting failure counter.")
|
||||
st.consecutive_fails = 0
|
||||
st.last_reboot_datetime = Dates.now()
|
||||
@show st
|
||||
@show StateFilePath
|
||||
save_state(st, StateFilePath)
|
||||
else
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Reboot attempt failed; will retry after next interval.")
|
||||
end
|
||||
end
|
||||
# println(5)
|
||||
end
|
||||
|
||||
function limitTextFileLines(LogFilePath::String; maxlines::Integer=100)
|
||||
log = readlines(LogFilePath)
|
||||
if length(log) < (maxlines - 1)
|
||||
total_lines = length(log)
|
||||
if total_lines < maxlines
|
||||
return nothing
|
||||
end
|
||||
exceeding_row = total_lines - maxlines # can be 0 or more
|
||||
reduced_lines = log[exceeding_row+2:end]
|
||||
reducedLog = ""
|
||||
for i in log[end-(maxlines-1):end]
|
||||
for i in reduced_lines
|
||||
reducedLog = reducedLog * i * "\n"
|
||||
end
|
||||
write(LogFilePath, reducedLog)
|
||||
end
|
||||
|
||||
# function limitTextFileLines(LogFilePath::String; maxlines::Integer=100)
|
||||
# log = readlines(LogFilePath)
|
||||
# if length(log) < (maxlines - 1)
|
||||
# return nothing
|
||||
# end
|
||||
# reducedLog = ""
|
||||
# for i in log[end-(maxlines-1):end]
|
||||
# reducedLog = reducedLog * i * "\n"
|
||||
# end
|
||||
# write(LogFilePath, reducedLog)
|
||||
# end
|
||||
|
||||
# Main loop: runs indefinitely every CHECK_INTERVAL_SECS
|
||||
function main_loop()
|
||||
# Ensure log file exists
|
||||
@@ -277,15 +364,16 @@ function main_loop()
|
||||
end
|
||||
end
|
||||
# limit log file to latest 100 events
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
thisFilePath = @__FILE__
|
||||
broadcast_msg("Broadcasting from file: $thisFilePath")
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Starting check loop. Checking router $ROUTER_IP every $(CHECK_INTERVAL_SECS) seconds.")
|
||||
st = load_state(StateFilePath)
|
||||
while true
|
||||
try
|
||||
perform_check!(st)
|
||||
catch e
|
||||
limitTextFileLines(LogFilePath; maxlines=100)
|
||||
logmsg("Error during check: $e")
|
||||
end
|
||||
sleep(CHECK_INTERVAL_SECS)
|
||||
|
||||
@@ -1,27 +1,108 @@
|
||||
[2026-03-11T15:44:25.256] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T15:44:26.277] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T15:45:26.318] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T15:49:03.012] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T15:49:03.985] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T15:50:04.059] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T15:51:04.131] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T15:52:04.197] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T15:53:04.266] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T16:10:04.474] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:10:05.449] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T16:12:13.704] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:12:14.671] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T16:13:14.215] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:13:15.192] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T16:14:19.623] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:14:20.610] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T16:14:54.601] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:14:55.573] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T16:15:48.563] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:15:49.540] Error during check: SystemError("opening file \"/home/ton/docker-programs/check_and_reboot/check_and_reboot_state.json\"", 13, nothing)
|
||||
[2026-03-11T16:27:47.181] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:30:28.572] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T16:43:50.213] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T17:37:15.954] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T20:38:46.720] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-11T20:50:40.732] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T10:49:28.409] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T10:50:49.333] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T10:50:50.033] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:51:50.626] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:52:50.699] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:53:50.763] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:54:50.784] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:55:50.800] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:56:51.025] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:57:51.056] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T10:58:51.132] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T11:04:22.285] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T11:10:08.650] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T11:10:10.725] Error during check: UndefVarError(:thisFilePath, 0x000000000000975f, :local)
|
||||
[2026-03-20T11:12:40.556] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T11:12:43.912] Error during check: SystemError("opening file \"test_ping_result.json\"", 2, nothing)
|
||||
[2026-03-20T12:42:13.923] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:42:15.861] Error during check: UndefVarError(:thisFilePath, 0x000000000000975f, :local)
|
||||
[2026-03-20T12:43:25.591] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:43:27.556] Error during check: UndefVarError(:thisFilePath, 0x000000000000975f, :local)
|
||||
[2026-03-20T12:44:06.281] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:44:08.202] Error during check: UndefVarError(:thisFilePath, 0x000000000000975f, :local)
|
||||
[2026-03-20T12:45:23.028] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:45:24.799] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T12:46:26.403] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T12:47:27.427] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T12:47:27.525] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T12:47:27.528] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T12:48:06.389] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:48:08.162] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T12:49:09.763] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T12:50:10.833] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T12:50:10.937] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T12:50:10.942] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T12:54:25.047] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:54:26.823] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T12:56:13.713] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:56:15.487] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T12:57:17.055] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T12:58:18.125] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T12:58:18.353] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T12:58:18.357] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T12:59:43.699] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T12:59:45.472] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T13:00:47.029] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T13:01:48.056] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T13:01:48.151] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T13:01:48.154] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T13:02:22.831] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:02:24.606] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 1/3.
|
||||
[2026-03-20T13:03:06.170] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:03:08.073] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T13:06:43.902] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:06:45.688] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T13:20:26.911] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:20:27.794] Error during check: SystemError("opening file \"test_ping_result.json\"", 2, nothing)
|
||||
[2026-03-20T13:22:32.247] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:22:34.026] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T13:23:38.078] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:23:39.856] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T13:24:16.835] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:24:18.606] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T13:24:19.209] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T13:24:19.213] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T13:25:20.400] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 1/3.
|
||||
[2026-03-20T13:26:21.625] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 2/3.
|
||||
[2026-03-20T13:27:22.681] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 3/3.
|
||||
[2026-03-20T13:28:23.700] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 4/3.
|
||||
[2026-03-20T13:29:04.947] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T13:29:06.721] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 5/3.
|
||||
[2026-03-20T14:32:48.752] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T14:32:50.528] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 6/3.
|
||||
[2026-03-20T14:32:51.123] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T14:32:51.128] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T14:33:52.347] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 1/3.
|
||||
[2026-03-20T14:34:53.367] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T14:35:54.418] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T14:35:54.452] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T14:35:54.455] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T14:36:55.528] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 1/3.
|
||||
[2026-03-20T14:38:00.916] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T14:38:02.688] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T14:39:04.303] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T14:39:04.396] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T14:39:04.398] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T14:39:32.271] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T14:39:34.046] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 1/3.
|
||||
[2026-03-20T14:40:27.209] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T14:40:28.984] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 2/3.
|
||||
[2026-03-20T14:41:30.736] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T14:41:30.836] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T14:41:30.839] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T14:42:13.075] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T14:42:14.852] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 1/3.
|
||||
[2026-03-20T14:43:15.578] 192.168.88.1 is reachable during cooldown. Router is back online! Resetting state.
|
||||
[2026-03-20T14:44:16.617] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T14:45:17.675] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T14:46:18.745] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T14:46:18.841] DRY RUN: would run reboot command: /usr/bin/sudo systemctl reboot
|
||||
[2026-03-20T14:46:18.844] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T15:21:15.466] Starting check loop. Checking router 192.168.88.1 every 60 seconds.
|
||||
[2026-03-20T15:21:17.191] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 1/3.
|
||||
[2026-03-20T15:22:18.736] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
[2026-03-20T15:23:19.802] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 3/3.
|
||||
[2026-03-20T15:23:19.865] DRY RUN: would run reboot command: /bin/systemctl reboot
|
||||
[2026-03-20T15:23:19.867] Reboot executed (or simulated). Resetting failure counter.
|
||||
[2026-03-20T15:24:21.083] 192.168.88.1 is unreachable during cooldown. Consecutive fails: 1/3.
|
||||
[2026-03-20T15:25:22.150] 192.168.88.1 is unreachable (last result: no response). Consecutive fails: 2/3.
|
||||
|
||||
1
test_ping_result.json
Normal file
1
test_ping_result.json
Normal file
@@ -0,0 +1 @@
|
||||
{"ok": false, "result": "no response"}
|
||||
Reference in New Issue
Block a user