3 changed files with 104 additions and 1 deletions
@ -0,0 +1,102 @@ |
|||||
|
-- Purpose: Minimal log watcher using `docker logs -f` as input. |
||||
|
-- Requirements: lua 5.4 + luasocket + docker CLI inside the container. |
||||
|
-- Notes: |
||||
|
-- - Pattern match is plain substring (fast & simple). |
||||
|
-- - Optional Wake-on-LAN is native (no external tools). |
||||
|
-- - Optional port-wait is provided but commented out (mirrors original bash idea). |
||||
|
|
||||
|
local socket = require("socket") |
||||
|
|
||||
|
local function getenv(name, def) |
||||
|
local v = os.getenv(name) |
||||
|
return (v ~= nil and v ~= "") and v or def |
||||
|
end |
||||
|
|
||||
|
-- ---- Config via env ---- |
||||
|
local CONTAINER_NAME = getenv("CONTAINER_NAME", "paperless-ai") |
||||
|
local SINCE = getenv("SINCE", "0s") |
||||
|
local OLLAMA_HOST = getenv("OLLAMA_HOST", "192.168.222.12") |
||||
|
local OLLAMA_PORT = tonumber(getenv("OLLAMA_PORT", "11434")) |
||||
|
local ERROR_PATTERN = getenv( |
||||
|
"ERROR_PATTERN", |
||||
|
("Error: [ERROR] Document analysis failed: connect EHOSTUNREACH %s:%d"):format(OLLAMA_HOST, OLLAMA_PORT) |
||||
|
) |
||||
|
|
||||
|
-- Optional Wake-on-LAN |
||||
|
local WOL_MAC = getenv("WOL_MAC", "") -- e.g. "AA:BB:CC:DD:EE:FF" |
||||
|
local WOL_BCAST = getenv("WOL_BCAST", "255.255.255.255") |
||||
|
local WOL_PORT = tonumber(getenv("WOL_PORT", "9")) |
||||
|
|
||||
|
-- Optional: wait for service to come up (kept commented to stay minimal) |
||||
|
-- local UP_WAIT_TIMEOUT = tonumber(getenv("UP_WAIT_TIMEOUT", "90")) |
||||
|
|
||||
|
local function log(msg) |
||||
|
io.stdout:write(os.date("[%F %T] "), msg, "\n"); io.stdout:flush() |
||||
|
end |
||||
|
|
||||
|
-- "AA:BB:CC:DD:EE:FF" -> 6 bytes |
||||
|
local function mac_to_bytes(mac) |
||||
|
local bytes = {} |
||||
|
for byte in mac:gmatch("(%x%x)") do table.insert(bytes, tonumber(byte, 16)) end |
||||
|
if #bytes ~= 6 then return nil end |
||||
|
return string.char(table.unpack(bytes)) |
||||
|
end |
||||
|
|
||||
|
local function send_wol(mac_str, bcast_ip, port) |
||||
|
local mb = mac_to_bytes(mac_str) |
||||
|
if not mb then return false, "invalid MAC" end |
||||
|
local packet = string.rep(string.char(0xFF), 6) .. mb:rep(16) |
||||
|
local udp = assert(socket.udp()) |
||||
|
udp:settimeout(2) |
||||
|
pcall(function() assert(udp:setoption("broadcast", true)) end) |
||||
|
local ok, err = udp:sendto(packet, bcast_ip, port) |
||||
|
udp:close() |
||||
|
return ok ~= nil, err |
||||
|
end |
||||
|
|
||||
|
-- Kept for reference; not used to keep parity with your minimal bash |
||||
|
-- local function port_is_up(host, port, timeout_sec) |
||||
|
-- local deadline = socket.gettime() + (timeout_sec or 1) |
||||
|
-- repeat |
||||
|
-- local tcp = socket.tcp(); tcp:settimeout(1) |
||||
|
-- if tcp:connect(host, port) then tcp:close(); return true end |
||||
|
-- tcp:close(); socket.sleep(0.5) |
||||
|
-- until socket.gettime() >= deadline |
||||
|
-- return false |
||||
|
-- end |
||||
|
|
||||
|
local function main() |
||||
|
log(("Watching container='%s' since='%s'"):format(CONTAINER_NAME, SINCE)) |
||||
|
log(("Looking for pattern: %q"):format(ERROR_PATTERN)) |
||||
|
|
||||
|
local cmd = ("docker logs -f --since %q %q 2>&1"):format(SINCE, CONTAINER_NAME) |
||||
|
local fh = assert(io.popen(cmd, "r")) |
||||
|
|
||||
|
for line in fh:lines() do |
||||
|
-- Plain substring match (no regex) |
||||
|
if line:find(ERROR_PATTERN, 1, true) ~= nil then |
||||
|
log(("Detected EHOSTUNREACH for Ollama (%s:%d)."):format(OLLAMA_HOST, OLLAMA_PORT)) |
||||
|
|
||||
|
if WOL_MAC ~= "" then |
||||
|
local ok, err = send_wol(WOL_MAC, WOL_BCAST, WOL_PORT) |
||||
|
if ok then |
||||
|
log(("Sent WOL to %s via %s:%d"):format(WOL_MAC, WOL_BCAST, WOL_PORT)) |
||||
|
else |
||||
|
log("WOL failed: " .. tostring(err)) |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
-- Optional wait (kept commented for minimal parity) |
||||
|
-- if port_is_up(OLLAMA_HOST, OLLAMA_PORT, UP_WAIT_TIMEOUT) then |
||||
|
-- log("Ollama reachable again.") |
||||
|
-- else |
||||
|
-- log("Timeout waiting for Ollama.") |
||||
|
-- end |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
fh:close() |
||||
|
log("Log stream ended.") |
||||
|
end |
||||
|
|
||||
|
main() |
||||
Loading…
Reference in new issue