2a3d780347
Adds `fn doctor` read-only diagnostic command with subcommands artefacts, services, sync, uses-functions, unused, and --json flag for agents. Each subcommand wraps a registry function in functions/infra/. New functions: - artefact_doctor, services_status, pc_locations_drift, audit_uses_functions, find_unused_functions (Go diagnostics) - backup_sqlite_db, rotate_backups, wait_for_http, wait_for_port, port_kill, tail_journal, pre_commit_hook_install (bash utilities) - notify_telegram (Go HTTP) - backup_all pipeline (tag launcher) Plus prior session leftovers (scan_secrets_in_dirty, append_diary_entry, git utilities, http_session_cookie_middleware, compile/full-git pipelines). Fixes pc_locations_drift filepath.Join bug with absolute dir_path. Documents fn doctor in CLAUDE.md, .claude/rules/fn_doctor.md (rule 23), docs/architecture.md, CHANGELOG.md (2026-05-07), and diary entry. First fn doctor uses-functions run found drift in 7/12 apps (deuda para sincronizar app.md con imports reales). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
78 lines
2.0 KiB
Bash
78 lines
2.0 KiB
Bash
#!/usr/bin/env bash
|
|
# tail_journal — wrapper sobre journalctl con formato consistente
|
|
|
|
tail_journal() {
|
|
local unit="${1:-}"
|
|
local lines="${2:-100}"
|
|
local follow="${3:-false}"
|
|
local since="${4:-}"
|
|
local priority="${5:-info}"
|
|
|
|
if [[ -z "$unit" ]]; then
|
|
echo "tail_journal: unit requerida" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Normalizar nombre de unit (añadir .service si no tiene extension)
|
|
local unit_full="$unit"
|
|
if [[ "$unit" != *.* ]]; then
|
|
unit_full="${unit}.service"
|
|
fi
|
|
|
|
# Validar prioridad
|
|
case "$priority" in
|
|
emerg|alert|crit|err|warning|notice|info|debug) ;;
|
|
*)
|
|
echo "tail_journal: prioridad invalida '$priority'. Valores: emerg alert crit err warning notice info debug" >&2
|
|
return 2
|
|
;;
|
|
esac
|
|
|
|
# Verificar que journalctl esta disponible
|
|
if ! command -v journalctl &>/dev/null; then
|
|
echo "tail_journal: journalctl no disponible" >&2
|
|
return 5
|
|
fi
|
|
|
|
# Detectar si la unit es de usuario o de sistema
|
|
local user_flag=""
|
|
if systemctl --user list-units --all 2>/dev/null | grep -q "$unit_full"; then
|
|
user_flag="--user"
|
|
fi
|
|
|
|
# Construir comando base
|
|
local -a cmd
|
|
if [[ -z "$user_flag" ]]; then
|
|
cmd=(sudo journalctl)
|
|
else
|
|
cmd=(journalctl --user)
|
|
fi
|
|
|
|
cmd+=(-u "$unit_full" -n "$lines" -p "$priority" --output=short-iso)
|
|
|
|
if [[ -n "$since" ]]; then
|
|
cmd+=(--since "$since")
|
|
fi
|
|
|
|
local follow_flag=false
|
|
if [[ "$follow" == "true" || "$follow" == "-f" ]]; then
|
|
follow_flag=true
|
|
cmd+=(-f)
|
|
fi
|
|
|
|
# Verificar que la unit existe (solo si no hay user_flag y no es sudo)
|
|
if [[ -n "$user_flag" ]]; then
|
|
if ! systemctl --user list-units --all 2>/dev/null | grep -q "$unit_full"; then
|
|
echo "tail_journal: unit '$unit_full' no encontrada" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Ejecutar sin bufferizar si follow=true
|
|
if [[ "$follow_flag" == "true" ]]; then
|
|
stdbuf -oL "${cmd[@]}"
|
|
else
|
|
"${cmd[@]}"
|
|
fi
|
|
}
|