From 90c4a720e3a7f93b94a47ef24b7686b585abccf6 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Wed, 9 Sep 2026 19:26:22 +0200 Subject: [PATCH] group host changes by function with a truthful before/after --- AppImage/components/audit-changes.tsx | 352 +++++++++++------- AppImage/messages/de/common.json | 12 +- AppImage/messages/en/common.json | 12 +- AppImage/messages/es/common.json | 12 +- AppImage/messages/fr/common.json | 12 +- AppImage/messages/it/common.json | 12 +- AppImage/messages/pt/common.json | 12 +- AppImage/messages/sk/common.json | 12 +- AppImage/messages/sv/common.json | 12 +- AppImage/scripts/changes_journal.py | 5 + install_proxmenux.sh | 12 + install_proxmenux_beta.sh | 12 + scripts/global/pmx_journal.sh | 8 +- scripts/post_install/auto_post_install.sh | 20 +- .../post_install/customizable_post_install.sh | 12 - 15 files changed, 333 insertions(+), 184 deletions(-) diff --git a/AppImage/components/audit-changes.tsx b/AppImage/components/audit-changes.tsx index 9a98ea99..b99a57ad 100644 --- a/AppImage/components/audit-changes.tsx +++ b/AppImage/components/audit-changes.tsx @@ -58,6 +58,29 @@ interface Summary { journal_started: number | null } +// A file that did not exist before was created, not replaced — a sysadmin +// reading this must see "new file", not "file replaced". `capture` carries +// that distinction: "created" for a file born here, "present" for one that +// already had contents we captured before overwriting them. +function operationLabelKey(change: { operation: string; capture: string }): string { + // Two truthful labels for a file: created if it did not exist, modified if + // it did. The diff below shows exactly what changed either way, so there is + // no need to distinguish write/edit/append in the label. + if (["write_file", "edit_file", "append_file"].includes(change.operation)) { + return change.capture === "created" ? "operation.file_created" : "operation.file_modified" + } + return `operation.${change.operation}` +} + +// Undoing follows `revert`, not `exactness`: a created file is undone by +// deleting it (there was nothing before), an overwritten one by restoring +// what we captured. +function undoKey(change: { revert: string; exactness: string }): string { + if (change.revert === "remove") return "undo.remove" + if (change.revert === "restore" && change.exactness === "exact") return "undo.restore" + return `exactness.${change.exactness}` +} + const CLASS_STYLE: Record = { configuration: { chip: "bg-blue-500/10 text-blue-400 border-blue-400/20", Icon: Settings2 }, installation: { chip: "bg-green-500/10 text-green-500 border-green-500/20", Icon: Package }, @@ -65,6 +88,144 @@ const CLASS_STYLE: Record = { registration: { chip: "bg-muted text-muted-foreground border-border", Icon: HelpCircle }, } +function ChangeCard({ change, expanded, onToggle, t, when }: { + change: Change; expanded: boolean; onToggle: () => void + t: (k: string, params?: Record) => string + when: (n: number) => string +}) { + const style = CLASS_STYLE[change.class] || CLASS_STYLE.registration + const Icon = style.Icon + const installed = String(change.detail?.installed || "") + return ( + + + + {expanded && ( + +
+ {t("audit.changes.source")}:{" "} + {change.source || "—"} + {change.revert && change.revert !== "none" && ( + {t("audit.changes.reversibility")}:{" "} + {t(`audit.changes.${undoKey(change)}`)} + )} +
+ + {(change.operation === "enable_service" || change.operation === "disable_service") + && Boolean(change.detail?.before_state || change.detail?.after_state) && ( +
+ + {String(change.detail?.before_state || "—").replace(/\s+/g, " ")} + + + + {String(change.detail?.after_state || "—").replace(/\s+/g, " ")} + +
+ )} + + {installed && ( +
+

+ {t("audit.changes.packagesAdded")} +

+
+ {installed.split(/\s+/).filter(Boolean).map((pkg) => ( + + {pkg} + + ))} +
+
+ )} + + {change.class === "execution" && Boolean(change.detail?.command) && ( +
+

+ {t("audit.changes.commandRun")} +

+
+                {String(change.detail.command)}
+              
+

+ {t("audit.changes.executionNote")} +

+
+ )} + + {change.diff && ( +
+

+ {t("audit.changes.difference")} +

+ {change.diff.available ? ( + <> +
+                    {(change.diff.hunks || []).map((line: string, i: number) => (
+                      
{line}
+ ))} +
+ {change.diff.truncated && ( +

+ {t("audit.changes.diffTruncated")} +

+ )} + + ) : ( +

+ {t("audit.changes.diffUnavailable")} +

+ )} +
+ )} + + {change.capture === "unknown" && ( +

+ {t("audit.changes.unknownNote")} +

+ )} +
+ )} +
+ ) +} + export function AuditChanges() { const t = useT() const { language } = useI18n() @@ -100,11 +261,34 @@ export function AuditChanges() { return next }) + const [openFn, setOpenFn] = useState>(new Set()) + const toggleFn = (fn: string) => setOpenFn((prev) => { + const next = new Set(prev) + next.has(fn) ? next.delete(fn) : next.add(fn) + return next + }) + const visible = useMemo( () => changes.filter((c) => filter === "all" || c.class === filter), [changes, filter], ) + // A sysadmin asks "what did each ProxMenux function do to my host?" — so + // the changes are grouped under the function that made them. Each group is + // one card; opening it reveals that function's individual file changes. + const groups = useMemo(() => { + const byFn = new Map() + for (const c of visible) { + const key = c.function || "—" + const g = byFn.get(key) || { function: key, version: c.function_version || "", last: 0, items: [] } + g.items.push(c) + if (c.recorded_at > g.last) g.last = c.recorded_at + if (c.function_version) g.version = c.function_version + byFn.set(key, g) + } + return Array.from(byFn.values()).sort((a, b) => b.last - a.last) + }, [visible]) + const when = (epoch: number) => new Date(epoch * 1000).toLocaleString(language) if (loading) { @@ -155,166 +339,54 @@ export function AuditChanges() { - {summary && summary.functions.length > 0 && ( - - - - {t("audit.changes.byFunction")} - - - - {summary.functions.map((fn) => ( - - ))} - - - )} -
- {visible.map((change) => { - const style = CLASS_STYLE[change.class] || CLASS_STYLE.registration - const Icon = style.Icon - const expanded = open.has(change.id) - const installed = String(change.detail?.installed || "") + {groups.map((g) => { + const fnOpen = openFn.has(g.function) return ( - + - {expanded && ( - -
- {t("audit.changes.function")}:{" "} - {change.function || "—"} - {change.function_version && ` v${change.function_version}`} - - {t("audit.changes.source")}:{" "} - {change.source || "—"} - {t("audit.changes.reversibility")}:{" "} - {t(`audit.changes.exactness.${change.exactness}`)} -
- - {installed && ( -
-

- {t("audit.changes.packagesAdded")} -

-
- {installed.split(/\s+/).filter(Boolean).map((pkg) => ( - - {pkg} - - ))} -
-
- )} - - {change.class === "execution" && Boolean(change.detail?.command) && ( -
-

- {t("audit.changes.commandRun")} -

-
-                        {String(change.detail.command)}
-                      
-

- {t("audit.changes.executionNote")} -

-
- )} - - {change.diff && ( -
-

- {t("audit.changes.difference")} -

- {change.diff.available ? ( - <> -
-                            {(change.diff.hunks || []).map((line: string, i: number) => (
-                              
{line}
- ))} -
- {change.diff.truncated && ( -

- {t("audit.changes.diffTruncated")} -

- )} - - ) : ( -

- {t("audit.changes.diffUnavailable")} -

- )} -
- )} - - {change.capture === "unknown" && ( -

- {t("audit.changes.unknownNote")} -

- )} + {fnOpen && ( + + {g.items.map((change) => ( + toggle(change.id)} + t={t} + when={when} + /> + ))} )}
) })} - {visible.length === 0 && summary && summary.total > 0 && ( + {groups.length === 0 && summary && summary.total > 0 && (

{t("audit.changes.noneInFilter")}

)}
diff --git a/AppImage/messages/de/common.json b/AppImage/messages/de/common.json index 8e165ea1..a053814c 100644 --- a/AppImage/messages/de/common.json +++ b/AppImage/messages/de/common.json @@ -5888,8 +5888,8 @@ "diffUnavailable": "Der ersetzte Inhalt ist nicht mehr gespeichert, der Unterschied lässt sich nicht zeigen.", "packagesAdded": "Hinzugefügte Pakete", "commandRun": "Ausgeführter Befehl", - "executionNote": "ProxMenux hat dies auf Anforderung ausgeführt; was sich änderte, entschied der Befehl, nicht ProxMenux.", - "unknownNote": "Dies wurde vor dem Journal angewandt, der ersetzte Zustand wurde nie erfasst.", + "executionNote": "ProxMenux hat diesen Befehl ausgeführt; was er geändert hat, bestimmt der Befehl selbst.", + "unknownNote": "Angewendet, bevor das Journal existierte, daher wurde der vorherige Zustand nicht erfasst.", "noneInFilter": "Keine Änderung dieser Art.", "class": { "all": "Alle", @@ -5900,7 +5900,11 @@ }, "operation": { "write_file": "Datei ersetzt", + "file_created": "Datei erstellt", + "file_modified": "Datei geändert", + "write_file_created": "Datei erstellt", "edit_file": "Datei bearbeitet", + "append_file": "An Datei angehängt", "remove_file": "Datei entfernt", "install_package": "Installiert", "enable_service": "Dienst aktiviert", @@ -5917,6 +5921,10 @@ "exact": "Stellt genau das Vorherige wieder her", "partial": "Teilweise: Abhängigkeiten können bleiben oder mitgehen", "none": "Aus dem Journal nicht rückgängig zu machen" + }, + "undo": { + "remove": "Löscht die Datei (vorher war keine vorhanden)", + "restore": "Stellt exakt den vorherigen Zustand wieder her" } }, "comparison": { diff --git a/AppImage/messages/en/common.json b/AppImage/messages/en/common.json index b2f8de1b..0aa35adb 100644 --- a/AppImage/messages/en/common.json +++ b/AppImage/messages/en/common.json @@ -5954,8 +5954,8 @@ "diffUnavailable": "The content that was replaced is no longer stored, so the difference cannot be shown.", "packagesAdded": "Packages added", "commandRun": "Command run", - "executionNote": "ProxMenux ran this on request; what it changed was decided by the command, not by ProxMenux.", - "unknownNote": "This was applied before the journal existed, so what it replaced was never captured.", + "executionNote": "ProxMenux ran this command; what it changed is up to the command itself.", + "unknownNote": "Applied before the journal existed, so the prior state was not captured.", "noneInFilter": "No change of this kind.", "class": { "all": "All", @@ -5966,7 +5966,11 @@ }, "operation": { "write_file": "File replaced", + "file_created": "File created", + "file_modified": "File modified", + "write_file_created": "File created", "edit_file": "File edited", + "append_file": "Appended to file", "remove_file": "File removed", "install_package": "Installed", "enable_service": "Service enabled", @@ -5983,6 +5987,10 @@ "exact": "Restores exactly what was there", "partial": "Partial: dependencies may remain or be removed with it", "none": "Cannot be undone from the journal" + }, + "undo": { + "remove": "Deletes the file (there was none before)", + "restore": "Restores exactly what was there" } }, "comparison": { diff --git a/AppImage/messages/es/common.json b/AppImage/messages/es/common.json index 2ef1fe18..8d23668b 100644 --- a/AppImage/messages/es/common.json +++ b/AppImage/messages/es/common.json @@ -5888,8 +5888,8 @@ "diffUnavailable": "El contenido sustituido ya no está almacenado, así que no se puede mostrar la diferencia.", "packagesAdded": "Paquetes añadidos", "commandRun": "Comando ejecutado", - "executionNote": "ProxMenux lo ejecutó a petición; lo que cambió lo decidió el comando, no ProxMenux.", - "unknownNote": "Esto se aplicó antes de que existiera el registro, así que nunca se capturó a qué sustituyó.", + "executionNote": "ProxMenux ejecutó este comando; lo que cambió lo determina el propio comando.", + "unknownNote": "Se aplicó antes de que existiera el registro, así que no se guardó el estado anterior.", "noneInFilter": "No hay ningún cambio de este tipo.", "class": { "all": "Todos", @@ -5900,7 +5900,11 @@ }, "operation": { "write_file": "Fichero reemplazado", + "file_created": "Fichero creado", + "file_modified": "Fichero modificado", + "write_file_created": "Fichero creado", "edit_file": "Fichero editado", + "append_file": "Se añadió al fichero", "remove_file": "Fichero eliminado", "install_package": "Instalado", "enable_service": "Servicio habilitado", @@ -5917,6 +5921,10 @@ "exact": "Restaura exactamente lo que había", "partial": "Parcial: pueden quedar dependencias o irse con ello", "none": "No se puede deshacer desde el registro" + }, + "undo": { + "remove": "Elimina el fichero (no había ninguno antes)", + "restore": "Restaura exactamente lo que había" } }, "comparison": { diff --git a/AppImage/messages/fr/common.json b/AppImage/messages/fr/common.json index 0c5b7654..73c57a54 100644 --- a/AppImage/messages/fr/common.json +++ b/AppImage/messages/fr/common.json @@ -5888,8 +5888,8 @@ "diffUnavailable": "Le contenu remplacé n'est plus stocké, la différence ne peut pas être montrée.", "packagesAdded": "Paquets ajoutés", "commandRun": "Commande exécutée", - "executionNote": "ProxMenux l'a exécutée à la demande ; ce qui a changé a été décidé par la commande, pas par ProxMenux.", - "unknownNote": "Ceci a été appliqué avant l'existence du journal ; l'état remplacé n'a jamais été capturé.", + "executionNote": "ProxMenux a exécuté cette commande ; ce qu'elle a changé dépend de la commande elle-même.", + "unknownNote": "Appliqué avant l'existence du journal, l'état précédent n'a donc pas été capturé.", "noneInFilter": "Aucune modification de ce type.", "class": { "all": "Toutes", @@ -5900,7 +5900,11 @@ }, "operation": { "write_file": "Fichier remplacé", + "file_created": "Fichier créé", + "file_modified": "Fichier modifié", + "write_file_created": "Fichier créé", "edit_file": "Fichier modifié", + "append_file": "Ajouté au fichier", "remove_file": "Fichier supprimé", "install_package": "Installé", "enable_service": "Service activé", @@ -5917,6 +5921,10 @@ "exact": "Restaure exactement ce qui était là", "partial": "Partiel : des dépendances peuvent rester ou partir avec", "none": "Ne peut pas être annulé depuis le journal" + }, + "undo": { + "remove": "Supprime le fichier (il n'y en avait aucun avant)", + "restore": "Restaure exactement ce qui existait" } }, "comparison": { diff --git a/AppImage/messages/it/common.json b/AppImage/messages/it/common.json index 0612724a..9eca75ce 100644 --- a/AppImage/messages/it/common.json +++ b/AppImage/messages/it/common.json @@ -5888,8 +5888,8 @@ "diffUnavailable": "Il contenuto sostituito non è più archiviato, quindi la differenza non si può mostrare.", "packagesAdded": "Pacchetti aggiunti", "commandRun": "Comando eseguito", - "executionNote": "ProxMenux lo ha eseguito su richiesta; ciò che è cambiato lo ha deciso il comando, non ProxMenux.", - "unknownNote": "È stato applicato prima che esistesse il registro, quindi ciò che ha sostituito non è mai stato catturato.", + "executionNote": "ProxMenux ha eseguito questo comando; ciò che ha cambiato dipende dal comando stesso.", + "unknownNote": "Applicato prima che esistesse il registro, quindi lo stato precedente non è stato acquisito.", "noneInFilter": "Nessuna modifica di questo tipo.", "class": { "all": "Tutte", @@ -5900,7 +5900,11 @@ }, "operation": { "write_file": "File sostituito", + "file_created": "File creato", + "file_modified": "File modificato", + "write_file_created": "File creato", "edit_file": "File modificato", + "append_file": "Aggiunto al file", "remove_file": "File rimosso", "install_package": "Installato", "enable_service": "Servizio abilitato", @@ -5917,6 +5921,10 @@ "exact": "Ripristina esattamente ciò che c'era", "partial": "Parziale: le dipendenze possono restare o andarsene con esso", "none": "Non si può annullare dal registro" + }, + "undo": { + "remove": "Elimina il file (prima non ce n'era nessuno)", + "restore": "Ripristina esattamente ciò che c'era" } }, "comparison": { diff --git a/AppImage/messages/pt/common.json b/AppImage/messages/pt/common.json index deac9602..463ba62b 100644 --- a/AppImage/messages/pt/common.json +++ b/AppImage/messages/pt/common.json @@ -5888,8 +5888,8 @@ "diffUnavailable": "O conteúdo substituído já não está guardado, pelo que a diferença não pode ser mostrada.", "packagesAdded": "Pacotes adicionados", "commandRun": "Comando executado", - "executionNote": "O ProxMenux executou-o a pedido; o que mudou foi decidido pelo comando, não pelo ProxMenux.", - "unknownNote": "Isto foi aplicado antes de existir o registo, pelo que nunca se capturou o que substituiu.", + "executionNote": "O ProxMenux executou este comando; o que mudou depende do próprio comando.", + "unknownNote": "Aplicado antes de o registo existir, por isso o estado anterior não foi capturado.", "noneInFilter": "Não há alterações deste tipo.", "class": { "all": "Todas", @@ -5900,7 +5900,11 @@ }, "operation": { "write_file": "Ficheiro substituído", + "file_created": "Ficheiro criado", + "file_modified": "Ficheiro modificado", + "write_file_created": "Ficheiro criado", "edit_file": "Ficheiro editado", + "append_file": "Acrescentado ao ficheiro", "remove_file": "Ficheiro removido", "install_package": "Instalado", "enable_service": "Serviço ativado", @@ -5917,6 +5921,10 @@ "exact": "Restaura exatamente o que lá estava", "partial": "Parcial: podem ficar dependências ou sair com ele", "none": "Não pode ser desfeito a partir do registo" + }, + "undo": { + "remove": "Elimina o ficheiro (não existia nenhum antes)", + "restore": "Restaura exatamente o que existia" } }, "comparison": { diff --git a/AppImage/messages/sk/common.json b/AppImage/messages/sk/common.json index 1f395f1d..b3155a56 100644 --- a/AppImage/messages/sk/common.json +++ b/AppImage/messages/sk/common.json @@ -5954,8 +5954,8 @@ "diffUnavailable": "Nahradený obsah už nie je uložený, rozdiel sa nedá zobraziť.", "packagesAdded": "Pridané balíky", "commandRun": "Spustený príkaz", - "executionNote": "ProxMenux to spustil na požiadanie; čo sa zmenilo, rozhodol príkaz, nie ProxMenux.", - "unknownNote": "Toto bolo použité pred vznikom denníka, takže nahradený stav sa nikdy nezachytil.", + "executionNote": "ProxMenux spustil tento príkaz; čo zmenil, určuje samotný príkaz.", + "unknownNote": "Použité skôr, než existoval denník, takže predchádzajúci stav sa nezachytil.", "noneInFilter": "Žiadna zmena tohto druhu.", "class": { "all": "Všetky", @@ -5966,7 +5966,11 @@ }, "operation": { "write_file": "Súbor nahradený", + "file_created": "Súbor vytvorený", + "file_modified": "Súbor zmenený", + "write_file_created": "Súbor vytvorený", "edit_file": "Súbor upravený", + "append_file": "Pridané do súboru", "remove_file": "Súbor odstránený", "install_package": "Nainštalované", "enable_service": "Služba povolená", @@ -5983,6 +5987,10 @@ "exact": "Obnoví presne to, čo tam bolo", "partial": "Čiastočné: závislosti môžu zostať alebo odísť s tým", "none": "Z denníka sa nedá vrátiť" + }, + "undo": { + "remove": "Odstráni súbor (predtým žiadny nebol)", + "restore": "Obnoví presne to, čo tam bolo" } }, "comparison": { diff --git a/AppImage/messages/sv/common.json b/AppImage/messages/sv/common.json index 432ae687..e4296f75 100644 --- a/AppImage/messages/sv/common.json +++ b/AppImage/messages/sv/common.json @@ -5889,8 +5889,8 @@ "diffUnavailable": "Innehållet som ersattes lagras inte längre, så skillnaden kan inte visas.", "packagesAdded": "Tillagda paket", "commandRun": "Kört kommando", - "executionNote": "ProxMenux körde detta på begäran; vad som ändrades avgjordes av kommandot, inte av ProxMenux.", - "unknownNote": "Detta tillämpades innan journalen fanns, så det som ersattes fångades aldrig.", + "executionNote": "ProxMenux körde detta kommando; vad det ändrade avgörs av kommandot självt.", + "unknownNote": "Tillämpades innan loggen fanns, så det tidigare tillståndet fångades inte.", "noneInFilter": "Ingen ändring av det slaget.", "class": { "all": "Alla", @@ -5901,7 +5901,11 @@ }, "operation": { "write_file": "Fil ersatt", + "file_created": "Fil skapad", + "file_modified": "Fil ändrad", + "write_file_created": "Fil skapad", "edit_file": "Fil redigerad", + "append_file": "Lades till i filen", "remove_file": "Fil borttagen", "install_package": "Installerat", "enable_service": "Tjänst aktiverad", @@ -5918,6 +5922,10 @@ "exact": "Återställer exakt det som fanns", "partial": "Delvis: beroenden kan bli kvar eller följa med", "none": "Kan inte ångras från journalen" + }, + "undo": { + "remove": "Tar bort filen (det fanns ingen tidigare)", + "restore": "Återställer exakt vad som fanns" } }, "comparison": { diff --git a/AppImage/scripts/changes_journal.py b/AppImage/scripts/changes_journal.py index 80983508..c107668b 100644 --- a/AppImage/scripts/changes_journal.py +++ b/AppImage/scripts/changes_journal.py @@ -240,6 +240,11 @@ def diff_of(entry: dict[str, Any]) -> Optional[dict[str, Any]]: if entry.get("class") != CLASS_CONFIGURATION: return None before_ref, after_ref = entry.get("before_ref"), entry.get("after_ref") + # A service enable/disable changes state, not file content: it carries + # before_state/after_state, no refs. With nothing to diff, there is no + # difference block to show — the state transition speaks for itself. + if not before_ref and not after_ref: + return None before = read_object(before_ref) if before_ref else "" after = read_object(after_ref) if after_ref else "" if before is None or after is None: diff --git a/install_proxmenux.sh b/install_proxmenux.sh index 59302c33..1342af03 100755 --- a/install_proxmenux.sh +++ b/install_proxmenux.sh @@ -835,6 +835,18 @@ install_normal_version() { # Only .sh files need the executable bit. Applying +x recursively would # also flag README.md, .json, .py etc. as executable for no reason. find "$BASE_DIR/scripts" -type f -name '*.sh' -exec chmod +x {} + + + # Register the base dependencies the installer put in place. They are + # installed in the dependency step, before this clone delivers + # pmx_journal.sh, so the journal cannot capture them as they happen — + # this records them once the engine is available. The recording side of + # pmx_journal.sh is pure bash and needs nothing else installed. + if [ -f "$BASE_DIR/scripts/global/pmx_journal.sh" ]; then + # shellcheck source=/dev/null + source "$BASE_DIR/scripts/global/pmx_journal.sh" + pmx_journal_context "install_proxmenux" "1.0" + pmx_record_applied "dialog, jq, curl, git" "1.0" "install_dependencies" + fi chmod +x "$BASE_DIR/install_proxmenux.sh" msg_ok "Necessary files created." diff --git a/install_proxmenux_beta.sh b/install_proxmenux_beta.sh index ed6796bd..1872e2d4 100644 --- a/install_proxmenux_beta.sh +++ b/install_proxmenux_beta.sh @@ -726,6 +726,18 @@ install_beta() { # also flag README.md, .json, .py etc. as executable for no reason. find "$BASE_DIR/scripts" -type f -name '*.sh' -exec chmod +x {} + + # Register the base dependencies the installer put in place. They are + # installed in the dependency step, before this clone delivers + # pmx_journal.sh, so the journal cannot capture them as they happen — + # this records them once the engine is available. The recording side of + # pmx_journal.sh is pure bash and needs nothing else installed. + if [ -f "$BASE_DIR/scripts/global/pmx_journal.sh" ]; then + # shellcheck source=/dev/null + source "$BASE_DIR/scripts/global/pmx_journal.sh" + pmx_journal_context "install_proxmenux" "1.0" + pmx_record_applied "dialog, jq, curl, git" "1.0" "install_dependencies" + fi + if [ -d "./oci" ]; then mkdir -p "$BASE_DIR/oci" cp -r "./oci/"* "$BASE_DIR/oci/" 2>/dev/null || true diff --git a/scripts/global/pmx_journal.sh b/scripts/global/pmx_journal.sh index caf08b62..9eb1af03 100644 --- a/scripts/global/pmx_journal.sh +++ b/scripts/global/pmx_journal.sh @@ -158,7 +158,7 @@ _pmx_journal_common() { # EOF pmx_write_file() { local path="$1" - local temp before after existed="false" + local temp before="" after="" existed="false" temp="$(mktemp)" || { cat > "$path"; return $?; } cat > "$temp" @@ -245,7 +245,7 @@ pmx_remove_file() { # printf 'ulimit -n 1048576\n' | pmx_append_file /root/.profile pmx_append_file() { local path="$1" - local temp before after existed="false" + local temp before="" after="" existed="false" temp="$(mktemp)" || { cat >> "$path"; return $?; } cat > "$temp" @@ -342,8 +342,8 @@ pmx_install_pkg() { _pmx_service_state() { local unit="$1" printf '%s/%s' \ - "$(systemctl is-enabled "$unit" 2>/dev/null || echo unknown)" \ - "$(systemctl is-active "$unit" 2>/dev/null || echo unknown)" + "$(systemctl is-enabled "$unit" 2>/dev/null | head -1 || echo unknown)" \ + "$(systemctl is-active "$unit" 2>/dev/null | head -1 || echo unknown)" } pmx_enable_service() { diff --git a/scripts/post_install/auto_post_install.sh b/scripts/post_install/auto_post_install.sh index 97f3f56a..97a6ddef 100644 --- a/scripts/post_install/auto_post_install.sh +++ b/scripts/post_install/auto_post_install.sh @@ -97,16 +97,6 @@ register_tool() { local state="$2" local version="${3:-1.0}" local source="${4:-${SCRIPT_SOURCE:-unknown}}" - # Same as in the customizable script: the one call every function - # already makes, so an applied tool reaches the journal even where - # the function itself still writes directly. - if declare -F pmx_record_applied >/dev/null 2>&1; then - PMX_JOURNAL_FUNCTION="${FUNCNAME[1]:-$tool}" \ - PMX_JOURNAL_VERSION="$version" \ - PMX_JOURNAL_SOURCE="$source" \ - pmx_record_applied "$tool" "$version" \ - "$([[ "$state" == "true" ]] && echo applied || echo removed)" - fi ensure_tools_json if [[ "$state" == "true" ]]; then jq --arg t "$tool" --arg ver "$version" --arg src "$source" \ @@ -1293,8 +1283,13 @@ EOF [ "$KEEP_MB" -lt 8 ] && KEEP_MB=8 - pmx_edit_file /etc/systemd/journald.conf '/^\[Journal\]/,$d' 2>/dev/null || true - pmx_append_file /etc/systemd/journald.conf </dev/null + cat </dev/null 2>&1; then - PMX_JOURNAL_FUNCTION="${FUNCNAME[1]:-$tool}" \ - PMX_JOURNAL_VERSION="$version" \ - PMX_JOURNAL_SOURCE="$source" \ - pmx_record_applied "$tool" "$version" \ - "$([[ "$state" == "true" ]] && echo applied || echo removed)" - fi ensure_tools_json if [[ "$state" == "true" ]]; then jq --arg t "$tool" --arg ver "$version" --arg src "$source" \