Give each orchestrator child its own log as well as the parent's
Everything a child printed was interleaved into the parent's log with forty other scripts, separated only by human headings that map to no script id — so scoped_log could answer for ten orchestrators and nothing else. tee rather than a redirect, so the parent keeps receiving exactly what it did before and this only adds a destination; PIPESTATUS[0] preserves the child's exit code through the pipe. Trimmed to 1000 lines like run_job.sh does, because LOG_DIR is tmpfs and an untrimmed chatty script spends RAM. Falls back to the original unpiped call when the log cannot be opened — a child must never be denied a run because somewhere to write about it could not be created.
This commit is contained in:
@@ -2115,6 +2115,19 @@ _orch_child_record() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Keeps a child's own log to the same ceiling run_job.sh keeps a job's: the last 1000 lines,
|
||||||
|
# replaced atomically. LOG_DIR is tmpfs, so an untrimmed chatty script spends RAM rather than disk,
|
||||||
|
# which is the worse of the two places to leak.
|
||||||
|
_orch_trim_log() {
|
||||||
|
local f="$1" n
|
||||||
|
[[ -f "$f" ]] || return 0
|
||||||
|
n=$(wc -l < "$f" 2>/dev/null) || return 0
|
||||||
|
(( n > 1000 )) || return 0
|
||||||
|
tail -n 1000 "$f" > "$f.tmp" 2>/dev/null && mv -f "$f.tmp" "$f" 2>/dev/null
|
||||||
|
rm -f "$f.tmp" 2>/dev/null
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
run_orch_child() {
|
run_orch_child() {
|
||||||
local entry="$1"
|
local entry="$1"
|
||||||
local script_args script_path script_name label extra_args run_args
|
local script_args script_path script_name label extra_args run_args
|
||||||
@@ -2137,17 +2150,43 @@ run_orch_child() {
|
|||||||
[[ "$DRY_RUN" == true ]] && run_args+=("--dry-run")
|
[[ "$DRY_RUN" == true ]] && run_args+=("--dry-run")
|
||||||
[[ "$ENABLE_LOGGING" == true ]] && run_args+=("--log")
|
[[ "$ENABLE_LOGGING" == true ]] && run_args+=("--log")
|
||||||
|
|
||||||
local _start _ec
|
local _start _ec _clog
|
||||||
_start=$(date +%s)
|
_start=$(date +%s)
|
||||||
log "Running: $label"
|
log "Running: $label"
|
||||||
_orch_child_record "${script_args[0]}" "$_start"
|
_orch_child_record "${script_args[0]}" "$_start"
|
||||||
if bash "$script_path" "${run_args[@]}"; then
|
|
||||||
|
# The child's output goes to its own log as well as the orchestrator's, so a script can be
|
||||||
|
# read on its own terms. Until now everything a child printed was interleaved into the
|
||||||
|
# parent's log with forty other scripts, and the only marker separating them was a human
|
||||||
|
# heading like "━━━ Media Cleaner — anime ━━━" that maps to no script id — which is why
|
||||||
|
# scoped_log could answer for ten orchestrators and nothing else.
|
||||||
|
#
|
||||||
|
# tee, not a redirect: the parent's log must keep receiving everything exactly as before, so
|
||||||
|
# this adds a destination rather than moving one. PIPESTATUS[0] is what preserves the child's
|
||||||
|
# exit code through the pipe — $? would report tee's.
|
||||||
|
#
|
||||||
|
# The whole thing is conditional on the log being writable, and falls back to the original
|
||||||
|
# unpiped call when it is not. A child must never fail, or be denied a run, because somewhere
|
||||||
|
# to write about it could not be opened.
|
||||||
|
_clog="${LOG_DIR:-}/${script_args[0]%.sh}.log"
|
||||||
|
if [[ -n "${LOG_DIR:-}" ]] && mkdir -p "$(dirname "$_clog")" 2>/dev/null \
|
||||||
|
&& : >> "$_clog" 2>/dev/null; then
|
||||||
|
printf '\n── %s ────────────────────────────────────────────────\n' \
|
||||||
|
"$(date '+%Y-%m-%d %H:%M:%S')" >> "$_clog" 2>/dev/null
|
||||||
|
bash "$script_path" "${run_args[@]}" 2>&1 | tee -a "$_clog"
|
||||||
|
_ec=${PIPESTATUS[0]}
|
||||||
|
_orch_trim_log "$_clog"
|
||||||
|
else
|
||||||
|
bash "$script_path" "${run_args[@]}"
|
||||||
|
_ec=$?
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( _ec == 0 )); then
|
||||||
log "$script_name — done in $(format_duration $(( $(date +%s) - _start )))"
|
log "$script_name — done in $(format_duration $(( $(date +%s) - _start )))"
|
||||||
_orch_child_record "${script_args[0]}" "$_start" 0
|
_orch_child_record "${script_args[0]}" "$_start" 0
|
||||||
JOB_PASS+=("$label")
|
JOB_PASS+=("$label")
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
_ec=$?
|
|
||||||
_orch_child_record "${script_args[0]}" "$_start" "$_ec"
|
_orch_child_record "${script_args[0]}" "$_start" "$_ec"
|
||||||
# Match the severity ladder run_job.sh already records against: exit 1 is a warning,
|
# Match the severity ladder run_job.sh already records against: exit 1 is a warning,
|
||||||
# exit 2+ is an error. The status in the run record was always derived that way, so a
|
# exit 2+ is an error. The status in the run record was always derived that way, so a
|
||||||
|
|||||||
Reference in New Issue
Block a user