feat(post-install): rebuild Log2RAM with the journal and task logs kept on disk

This commit is contained in:
MacRimi
2026-10-27 19:48:26 +01:00
parent ac9b8c2705
commit 4cefc0484b
57 changed files with 992 additions and 1065 deletions
+73
View File
@@ -0,0 +1,73 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Folders of /var/log that Log2RAM leaves on disk
# ==========================================================
# Runs before Log2RAM puts /var/log in RAM. The journal, the task logs of
# Proxmox VE and those of Proxmox Backup Server are records a host needs after
# a power cut, and a task cannot run if its log cannot be written, so they
# stay on disk: each folder moves to
# /var/hdd.<name> and its usual place becomes a link to it. Log2RAM copies a
# link as a link, so their contents never enter the RAM.
#
# With PMX_L2R_REVERT=1 it puts the folders back in /var/log and removes the
# links; the uninstaller runs it that way at the next boot.
#
# PMX_L2R_ROOT prefixes every path, for tests.
# ==========================================================
ROOT="${PMX_L2R_ROOT:-}"
LOG_DIR="$ROOT/var/log"
# Only while /var/log is the folder on disk, never the copy in RAM.
if [ -z "$ROOT" ] && mountpoint -q /var/log; then
exit 0
fi
KEPT_ON_DISK="journal pve proxmox-backup"
keep_on_disk() {
local name="$1"
local place="$LOG_DIR/$name" disk="$ROOT/var/hdd.$name"
if [ -L "$place" ]; then
[ -d "$disk" ] || mkdir -p "$disk"
return 0
fi
# The journal is always kept on disk; any other folder only where it exists.
if [ ! -d "$place" ]; then
[ "$name" = journal ] || return 0
mkdir -p "$disk"
chown root:systemd-journal "$disk" 2>/dev/null || true
chmod 2755 "$disk"
elif [ ! -e "$disk" ]; then
mv "$place" "$disk" || return 1
else
cp -a "$place/." "$disk/" || return 1
rm -rf "${place:?}"
fi
ln -s "/var/hdd.$name" "$place"
}
put_back() {
local name="$1"
local place="$LOG_DIR/$name" disk="$ROOT/var/hdd.$name"
[ -d "$disk" ] || { [ -L "$place" ] && rm -f "$place"; return 0; }
[ -L "$place" ] && rm -f "$place"
if [ ! -e "$place" ]; then
mv "$disk" "$place" || return 1
else
cp -a "$disk/." "$place/" || return 1
rm -rf "${disk:?}"
fi
}
status=0
for name in $KEPT_ON_DISK; do
if [ "${PMX_L2R_REVERT:-0}" = 1 ]; then
put_back "$name" || status=1
else
keep_on_disk "$name" || status=1
fi
done
exit "$status"
+214
View File
@@ -0,0 +1,214 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Log2RAM setup shared by both post-install modes
# ==========================================================
# Log2RAM keeps /var/log in RAM and writes it to disk on a schedule. The
# journal and the task logs of Proxmox VE and Proxmox Backup Server stay on
# disk: see log2ram_keep_on_disk.sh, which moves them before Log2RAM starts.
#
# Requires utils.sh (translate, msg_*) and pmx_journal.sh (pmx_write_file...).
# ==========================================================
PMX_L2R_TAG="1.7.2"
PMX_L2R_COMMIT="f171449530f8984374c8f69fff3c92af813a694b"
PMX_L2R_REPO="https://github.com/azlux/log2ram.git"
PMX_L2R_SCRIPTS="/usr/local/share/proxmenux/scripts/global"
PMX_L2R_REVERT_UNIT="/etc/systemd/system/proxmenux-log2ram-revert.service"
# Size in MB and sync interval in hours proposed for this host's RAM.
pmx_log2ram_default_size() {
local ram_gb
ram_gb="$(awk '/^MemTotal:/{print int($2/1024/1024)}' /proc/meminfo)"
if (( ${ram_gb:-4} <= 8 )); then echo 128
elif (( ram_gb <= 16 )); then echo 256
else echo 512; fi
}
pmx_log2ram_default_hours() {
local ram_gb
ram_gb="$(awk '/^MemTotal:/{print int($2/1024/1024)}' /proc/meminfo)"
if (( ${ram_gb:-4} <= 8 )); then echo 1
elif (( ram_gb <= 16 )); then echo 3
else echo 6; fi
}
# What an installed Log2RAM is set to, for an update to keep it.
pmx_log2ram_current_size() {
local size
size="$(grep -E '^SIZE=' /etc/log2ram.conf 2>/dev/null | tail -1 | cut -d= -f2 | tr -dc '0-9')"
echo "${size:-$(pmx_log2ram_default_size)}"
}
pmx_log2ram_current_hours() {
local hours
hours="$(sed -n 's/^OnCalendar=\*-\*-\* 00\/\([0-9]*\):55:00$/\1/p' \
/etc/systemd/system/log2ram-daily.timer.d/proxmenux.conf 2>/dev/null)"
# Earlier versions synced from a cron entry: "0 */N * * * root ... write".
[[ -n "$hours" ]] || hours="$(sed -n 's/^0 \*\/\([0-9]*\) .*log2ram write.*/\1/p' /etc/cron.d/log2ram 2>/dev/null)"
echo "${hours:-$(pmx_log2ram_default_hours)}"
}
# Size-based rotation for the API logs of Proxmox Backup Server, whose
# package ships no rule for them.
_pmx_log2ram_pbs_logrotate() {
dpkg-query -W -f='${Status}' proxmox-backup-server 2>/dev/null | grep -q 'install ok installed' || return 0
pmx_write_file /etc/logrotate.d/proxmox-backup-api <<'EOF'
/var/log/proxmox-backup/api/access.log /var/log/proxmox-backup/api/auth.log {
size 20M
rotate 3
compress
missingok
notifempty
copytruncate
}
EOF
chmod 0644 /etc/logrotate.d/proxmox-backup-api
}
# Files of the Log2RAM release, copied from a verified checkout. Its own
# install.sh is not run: it refuses to run while Log2RAM is active and starts
# by deleting /var/hdd.log, which is the disk copy of /var/log while mounted.
_pmx_log2ram_install_release() {
local checkout="/tmp/log2ram-${PMX_L2R_TAG}"
rm -rf "$checkout"
if ! git clone --quiet --depth 1 --branch "$PMX_L2R_TAG" "$PMX_L2R_REPO" "$checkout" >/dev/null 2>&1; then
msg_error "$(translate "Log2RAM could not be downloaded")"
return 1
fi
if [[ "$(git -C "$checkout" rev-parse HEAD 2>/dev/null)" != "$PMX_L2R_COMMIT" ]]; then
rm -rf "$checkout"
msg_error "$(translate "The downloaded Log2RAM does not match the expected release")"
return 1
fi
mkdir -p /usr/local/bin
install -m 644 "$checkout/log2ram.service" /etc/systemd/system/log2ram.service
install -m 644 "$checkout/log2ram-daily.service" /etc/systemd/system/log2ram-daily.service
install -m 644 "$checkout/log2ram-daily.timer" /etc/systemd/system/log2ram-daily.timer
install -m 755 "$checkout/log2ram" /usr/local/bin/log2ram
[[ -d /etc/logrotate.d ]] && install -m 644 "$checkout/log2ram.logrotate" /etc/logrotate.d/log2ram
[[ -f /etc/log2ram.conf ]] || install -m 644 "$checkout/log2ram.conf" /etc/log2ram.conf
rm -rf "$checkout"
}
# What earlier versions of this function installed and this one replaces.
_pmx_log2ram_remove_legacy() {
local path
for path in /etc/cron.d/log2ram /usr/local/bin/log2ram-check.sh \
/etc/cron.hourly/proxmox-backup-logrotate \
/usr/local/bin/log2ram.proxmenux.bak /usr/sbin/log2ram.proxmenux.bak; do
pmx_remove_file "$path" 2>/dev/null || true
done
}
# pmx_log2ram_setup SIZE_MB SYNC_HOURS WATCH(true|false)
pmx_log2ram_setup() {
local size_mb="$1" hours="$2" watch="$3"
local keep_free_mb=$(( size_mb / 2 ))
command -v rsync >/dev/null 2>&1 || pmx_install_pkg rsync
command -v git >/dev/null 2>&1 || pmx_install_pkg git
msg_info "$(translate "Installing Log2RAM") ${PMX_L2R_TAG}..."
_pmx_log2ram_install_release || return 1
msg_ok "$(translate "Log2RAM installed:") ${PMX_L2R_TAG}"
# The journal is not in RAM, so Log2RAM does not rotate it before a sync;
# and Proxmox has no mail command for its error notice.
pmx_edit_file /etc/log2ram.conf \
-e "s/^SIZE=.*/SIZE=${size_mb}M/" \
-e "s/^JOURNALD_AWARE=.*/JOURNALD_AWARE=false/" \
-e "s/^#\?NOTIFICATION=.*/NOTIFICATION=false/"
grep -q '^NOTIFICATION=' /etc/log2ram.conf || printf 'NOTIFICATION=false\n' | pmx_append_file /etc/log2ram.conf
mkdir -p /etc/systemd/system/log2ram.service.d /etc/systemd/system/log2ram-daily.timer.d
pmx_write_file /etc/systemd/system/log2ram.service.d/proxmenux.conf <<EOF
# ProxMenux: the journal stays on disk, and a sync is on disk when it ends.
[Service]
ExecStartPre=-${PMX_L2R_SCRIPTS}/log2ram_keep_on_disk.sh
ExecReload=
ExecReload=/usr/local/bin/log2ram write
ExecReload=/bin/sync -f /var/hdd.log
EOF
pmx_write_file /etc/systemd/system/log2ram-daily.timer.d/proxmenux.conf <<EOF
# ProxMenux: /var/log is written to disk every ${hours} hour(s).
[Timer]
OnCalendar=
OnCalendar=*-*-* 00/${hours}:55:00
EOF
mkdir -p /etc/systemd/journald.conf.d
pmx_write_file /etc/systemd/journald.conf.d/proxmenux-log2ram.conf <<EOF
# ProxMenux: the journal is kept on disk, outside the Log2RAM folder.
# SystemKeepFree also bounds it while it is still in RAM, until the next boot.
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=${keep_free_mb}M
# MaxLevelStore=info: required for ProxMenux Monitor log display and Fail2Ban detection.
MaxLevelStore=info
EOF
# The journal folder is a link; the attribute for btrfs goes to its target.
pmx_write_file /etc/tmpfiles.d/journal-nocow.conf <<'EOF'
# ProxMenux: /var/log/journal links to /var/hdd.journal while Log2RAM is installed.
h /var/hdd.journal - - - - +C
h /var/hdd.journal/%m - - - - +C
h /var/hdd.journal/remote - - - - +C
EOF
if [[ "$watch" == true ]]; then
pmx_write_file /etc/cron.d/log2ram-auto-sync <<EOF
# ProxMenux: past 85% of its size, /var/log in RAM is rotated and written to disk.
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
3-59/10 * * * * root nice -n 19 ionice -c 3 ${PMX_L2R_SCRIPTS}/log2ram_watch.sh >/dev/null 2>&1
EOF
chmod 0644 /etc/cron.d/log2ram-auto-sync
else
pmx_remove_file /etc/cron.d/log2ram-auto-sync 2>/dev/null || true
fi
_pmx_log2ram_pbs_logrotate
_pmx_log2ram_remove_legacy
pmx_remove_file "$PMX_L2R_REVERT_UNIT" 2>/dev/null || true
systemctl daemon-reload >/dev/null 2>&1 || true
pmx_apply_setting "service-enabled:log2ram" "systemctl is-enabled log2ram" \
systemctl enable log2ram.service log2ram-daily.timer || return 1
msg_ok "$(translate "Log2RAM keeps /var/log in RAM; the journal stays on disk from the next boot")"
}
# Log2RAM stops at the next shutdown, writing /var/log to disk on its way;
# the boot after that puts the journal back in /var/log.
pmx_log2ram_remove() {
pmx_disable_service log2ram-daily.timer 2>/dev/null || true
systemctl disable log2ram.service >/dev/null 2>&1 || true
local path
for path in /etc/cron.d/log2ram-auto-sync /etc/systemd/journald.conf.d/proxmenux-log2ram.conf \
/etc/tmpfiles.d/journal-nocow.conf /etc/systemd/system/log2ram.service.d/proxmenux.conf \
/etc/systemd/system/log2ram-daily.timer.d/proxmenux.conf; do
pmx_remove_file "$path" 2>/dev/null || true
done
_pmx_log2ram_remove_legacy
pmx_write_file "$PMX_L2R_REVERT_UNIT" <<EOF
[Unit]
Description=ProxMenux: put the journal back in /var/log after removing Log2RAM
DefaultDependencies=no
After=local-fs.target
Before=systemd-journald.service sysinit.target
ConditionPathExists=!/etc/systemd/system/sysinit.target.wants/log2ram.service
[Service]
Type=oneshot
Environment=PMX_L2R_REVERT=1
ExecStart=-${PMX_L2R_SCRIPTS}/log2ram_keep_on_disk.sh
ExecStart=/bin/sh -c 'mountpoint -q /var/hdd.log || rmdir /var/hdd.log 2>/dev/null; rm -f /usr/local/bin/log2ram /usr/local/bin/uninstall-log2ram.sh /etc/log2ram.conf /etc/logrotate.d/log2ram /etc/systemd/system/log2ram.service /etc/systemd/system/log2ram-daily.service /etc/systemd/system/log2ram-daily.timer; rmdir /etc/systemd/system/log2ram.service.d /etc/systemd/system/log2ram-daily.timer.d 2>/dev/null; systemctl disable proxmenux-log2ram-revert.service; rm -f ${PMX_L2R_REVERT_UNIT}; systemctl daemon-reload'
[Install]
WantedBy=sysinit.target
EOF
systemctl daemon-reload >/dev/null 2>&1 || true
systemctl enable proxmenux-log2ram-revert.service >/dev/null 2>&1 || true
}
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# ==========================================================
# ProxMenux - Keeps the Log2RAM folder from filling up
# ==========================================================
# Past 85% of its size, the logs in RAM are rotated and the ones just rotated
# are compressed at once, then everything is written to disk. Rules with
# delaycompress, such as the one of pveproxy, would otherwise leave the largest
# log uncompressed until the next day. No log is emptied.
# ==========================================================
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
mountpoint -q /var/log || exit 0
used="$(df --output=pcent /var/log 2>/dev/null | tail -1 | tr -dc '0-9')"
[ "${used:-0}" -ge 85 ] || exit 0
exec 9>/run/proxmenux-log2ram-watch.lock || exit 0
flock -n 9 || exit 0
logrotate -f /etc/logrotate.conf >/dev/null 2>&1 || true
find /var/log -xdev -type f -name '*.1' -exec gzip -9 -- {} + 2>/dev/null || true
systemctl reload log2ram >/dev/null 2>&1 || true
+4 -3
View File
@@ -205,11 +205,12 @@ update_pve_safe() {
fi
# The package list rides in the same dialog as the summary, so the
# decision is taken knowing what is about to be replaced. --scrolltext
# keeps the buttons reachable however long the list is.
# decision is taken knowing what is about to be replaced. Keep Yes focused
# while the list remains scrollable; --keep-tite restores the execution screen.
menu_text+="$(translate "Packages to be upgraded"):\n$upgradable_list\n\n"
menu_text+="$(translate "Do you want to proceed with the system update?")"
if ! whiptail --title "$(translate "Proxmox Update")" --scrolltext --yesno "$menu_text" 24 78; then
if ! dialog --keep-tite --title "$(translate "Proxmox Update")" \
--default-button yes --no-collapse --scrollbar --yesno "$menu_text" 24 78; then
msg_info2 "$(translate "Update cancelled by user")"
apt-get -y autoremove >/dev/null 2>&1 || true
apt-get -y autoclean >/dev/null 2>&1 || true
+4 -2
View File
@@ -169,10 +169,12 @@ EOF
else
# The package list rides in the same dialog as the summary, so
# the decision is taken knowing what is about to be replaced.
# --scrolltext keeps the buttons reachable however long it is.
# Keep Yes focused while the full package list remains scrollable.
# --keep-tite restores the execution screen after confirmation.
menu_text+="$(translate "Packages to be upgraded"):\n$upgradable_list\n\n"
menu_text+="$(translate "Do you want to proceed with the system update?")"
if whiptail --title "$(translate "Proxmox Update")" --scrolltext --yesno "$menu_text" 24 78; then
if dialog --keep-tite --title "$(translate "Proxmox Update")" \
--default-button yes --no-collapse --scrollbar --yesno "$menu_text" 24 78; then
return 0
else
return 1
+4 -2
View File
@@ -272,10 +272,12 @@ EOF
else
# The package list rides in the same dialog as the summary, so
# the decision is taken knowing what is about to be replaced.
# --scrolltext keeps the buttons reachable however long it is.
# Keep Yes focused while the full package list remains scrollable.
# --keep-tite restores the execution screen after confirmation.
menu_text+="$(translate "Packages to be upgraded"):\n$upgradable_list\n\n"
menu_text+="$(translate "Do you want to proceed with the system update?")"
if whiptail --title "$(translate "Proxmox Update")" --scrolltext --yesno "$menu_text" 24 78; then
if dialog --keep-tite --title "$(translate "Proxmox Update")" \
--default-button yes --no-collapse --scrollbar --yesno "$menu_text" 24 78; then
return 0
else
return 1
-15
View File
@@ -401,18 +401,3 @@ pmx_rebuild_dkms_after_kernel() {
fi
return 0
}
# Log2RAM syncs only the archived journal files, so the active file it found
# on disk when it was installed stays there. Restored at every boot, it makes
# journald continue an old sequence and delete its newest archives first.
# The sync removes that file from the disk copy. Returns 0 when it changes
# the given Log2RAM script.
pmx_log2ram_drop_stale_journal() {
local log2ram_bin="$1"
[[ -f "$log2ram_bin" ]] || return 1
grep -q -- '--exclude=journal/\*/\*' "$log2ram_bin" 2>/dev/null || return 1
grep -q -- '--delete-excluded' "$log2ram_bin" 2>/dev/null && return 1
[[ -e "${log2ram_bin}.proxmenux.bak" ]] || cp -a "$log2ram_bin" "${log2ram_bin}.proxmenux.bak"
sed '/optional_params+=("--exclude=journal\/\*\/\*")/a\ optional_params+=("--delete-excluded")' "$log2ram_bin" \
| pmx_write_file "$log2ram_bin"
}
+7 -396
View File
@@ -53,6 +53,9 @@ fi
if [[ -f "$LOCAL_SCRIPTS/global/pmx_journal.sh" ]]; then
source "$LOCAL_SCRIPTS/global/pmx_journal.sh"
fi
if [[ -f "$LOCAL_SCRIPTS/global/log2ram_setup.sh" ]]; then
source "$LOCAL_SCRIPTS/global/log2ram_setup.sh"
fi
load_language
initialize_cache
@@ -959,148 +962,18 @@ EOF
_update_existing_log2ram_auto() {
local func_version="$1"
local log2ram_bin=""
local candidate resolved tmp_file
pmx_journal_context "_update_existing_log2ram_auto" "$func_version"
msg_ok "$(translate "Log2RAM already registered — updating to latest configuration")"
for candidate in \
"$(command -v log2ram 2>/dev/null)" \
/usr/local/bin/log2ram \
/usr/sbin/log2ram \
/usr/bin/log2ram
do
[[ -n "$candidate" && -f "$candidate" ]] || continue
resolved="$(readlink -f "$candidate" 2>/dev/null || printf '%s' "$candidate")"
[[ -f "$resolved" ]] || continue
log2ram_bin="$resolved"
break
done
if [[ -z "$log2ram_bin" || ! -f /etc/log2ram.conf ]]; then
msg_error "$(translate "Log2RAM installation verification failed. Check /tmp/log2ram_install.log")"
return 1
fi
if grep -q 'rsync -aAXv ' "$log2ram_bin" 2>/dev/null; then
[[ -e "${log2ram_bin}.proxmenux.bak" ]] || cp -a "$log2ram_bin" "${log2ram_bin}.proxmenux.bak"
sed 's/rsync -aAXv /rsync -aXv --no-acls /g' "$log2ram_bin" | pmx_write_file "$log2ram_bin"
fi
if pmx_log2ram_drop_stale_journal "$log2ram_bin"; then
NECESSARY_REBOOT=1
msg_ok "$(translate "Log2RAM keeps the journal in order from the next reboot")"
fi
if dpkg-query -W -f='${Status}' proxmox-backup-server 2>/dev/null \
| grep -q 'install ok installed'; then
tmp_file="$(mktemp /etc/logrotate.d/.proxmox-backup-api.XXXXXX)" || return 1
cat > "$tmp_file" <<'EOF'
/var/log/proxmox-backup/api/access.log /var/log/proxmox-backup/api/auth.log {
size 20M
rotate 3
compress
missingok
notifempty
copytruncate
}
EOF
chmod 0644 "$tmp_file"
chown root:root "$tmp_file"
pmx_write_file /etc/logrotate.d/proxmox-backup-api < "$tmp_file"
rm -f "$tmp_file"
tmp_file="$(mktemp /etc/cron.hourly/.proxmox-backup-logrotate.XXXXXX)" || return 1
cat > "$tmp_file" <<'EOF'
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1
EOF
chmod 0755 "$tmp_file"
chown root:root "$tmp_file"
pmx_write_file /etc/cron.hourly/proxmox-backup-logrotate < "$tmp_file"
chmod 0755 /etc/cron.hourly/proxmox-backup-logrotate
chown root:root /etc/cron.hourly/proxmox-backup-logrotate
rm -f "$tmp_file"
msg_ok "$(translate "PBS API log rotation configured (hourly, size-based)")"
fi
tmp_file="$(mktemp /usr/local/bin/.log2ram-check.XXXXXX)" || return 1
cat > "$tmp_file" <<'EOF'
#!/usr/bin/env bash
# Watch /var/log usage on Log2RAM's tmpfs and act at two thresholds:
# > 80% → vacuum journald down to ~30% of SIZE, then log2ram write
# > 92% → aggressive: journal to ~5%, rotate PBS API logs if present,
# truncate existing pveproxy/pveam logs, then log2ram write
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CONF_FILE="/etc/log2ram.conf"
L2R_BIN="$(command -v log2ram || true)"
[[ -z "$L2R_BIN" && -x /usr/sbin/log2ram ]] && L2R_BIN="/usr/sbin/log2ram"
[[ -z "$L2R_BIN" ]] && exit 0
SIZE_MiB="$(grep -E '^SIZE=' "$CONF_FILE" 2>/dev/null | cut -d'=' -f2 | tr -dc '0-9')"
[[ -z "$SIZE_MiB" ]] && SIZE_MiB=128
LIMIT_BYTES=$(( SIZE_MiB * 1024 * 1024 ))
WARN_BYTES=$(( LIMIT_BYTES * 80 / 100 ))
EMERGENCY_BYTES=$(( LIMIT_BYTES * 92 / 100 ))
USED_BYTES="$(df -B1 --output=used /var/log 2>/dev/null | tail -1 | tr -dc '0-9')"
[[ -z "$USED_BYTES" ]] && exit 0
LOCK="/run/log2ram-check.lock"
exec 9>"$LOCK" 2>/dev/null || exit 0
flock -n 9 || exit 0
if (( USED_BYTES > EMERGENCY_BYTES )); then
SAFE_JOURNAL_MB=$(( SIZE_MiB * 5 / 100 ))
[[ "$SAFE_JOURNAL_MB" -lt 16 ]] && SAFE_JOURNAL_MB=16
journalctl --vacuum-size="${SAFE_JOURNAL_MB}M" >/dev/null 2>&1 || true
if [[ -x /usr/sbin/logrotate && -f /etc/logrotate.d/proxmox-backup-api ]]; then
/usr/sbin/logrotate -f /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1 || true
fi
[ -e /var/log/pveproxy/access.log ] && : > /var/log/pveproxy/access.log 2>/dev/null || true
[ -e /var/log/pveproxy/error.log ] && : > /var/log/pveproxy/error.log 2>/dev/null || true
[ -e /var/log/pveam.log ] && : > /var/log/pveam.log 2>/dev/null || true
"$L2R_BIN" write 2>/dev/null || true
elif (( USED_BYTES > WARN_BYTES )); then
SOFT_JOURNAL_MB=$(( SIZE_MiB * 30 / 100 ))
[[ "$SOFT_JOURNAL_MB" -lt 32 ]] && SOFT_JOURNAL_MB=32
journalctl --vacuum-size="${SOFT_JOURNAL_MB}M" >/dev/null 2>&1 || true
"$L2R_BIN" write 2>/dev/null || true
fi
EOF
chmod 0755 "$tmp_file"
chown root:root "$tmp_file"
bash -n "$tmp_file" || return 1
pmx_write_file /usr/local/bin/log2ram-check.sh < "$tmp_file"
chmod 0755 /usr/local/bin/log2ram-check.sh
chown root:root /usr/local/bin/log2ram-check.sh
rm -f "$tmp_file"
tmp_file="$(mktemp /etc/cron.d/.log2ram-auto-sync.XXXXXX)" || return 1
cat > "$tmp_file" <<'EOF'
# Log2RAM auto-sync based on /var/log usage - Created by ProxMenux
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
# nice/ionice keep the check off the priority queue for scheduled tasks.
3-59/10 * * * * root nice -n 19 ionice -c 3 /usr/local/bin/log2ram-check.sh >/dev/null 2>&1
EOF
chmod 0644 "$tmp_file"
chown root:root "$tmp_file"
pmx_write_file /etc/cron.d/log2ram-auto-sync < "$tmp_file"
chmod 0644 /etc/cron.d/log2ram-auto-sync
chown root:root /etc/cron.d/log2ram-auto-sync
rm -f "$tmp_file"
pmx_log2ram_setup "$(pmx_log2ram_current_size)" "$(pmx_log2ram_current_hours)" true || return 1
NECESSARY_REBOOT=1
register_tool "log2ram" true "$func_version"
msg_success "$(translate "Log2RAM installation and configuration completed successfully.")"
}
install_log2ram_auto() {
local FUNC_VERSION="1.8"
local FUNC_VERSION="2.0"
local existing_log2ram_bin=""
pmx_journal_context "install_log2ram_auto" "$FUNC_VERSION"
@@ -1156,270 +1029,8 @@ install_log2ram_auto() {
fi # end first-time install block
msg_info "$(translate "Cleaning previous Log2RAM installation...")"
pmx_disable_service log2ram || true
pmx_disable_service log2ram-daily.timer || true
local obsolete_path
for obsolete_path in \
/etc/cron.d/log2ram /etc/cron.d/log2ram-auto-sync \
/etc/cron.hourly/log2ram /etc/cron.daily/log2ram \
/etc/cron.weekly/log2ram /etc/cron.monthly/log2ram \
/usr/local/bin/log2ram-check.sh /usr/local/bin/log2ram /usr/sbin/log2ram \
/etc/systemd/system/log2ram.service \
/etc/systemd/system/log2ram-daily.timer \
/etc/systemd/system/log2ram-daily.service \
/etc/systemd/system/sysinit.target.wants/log2ram.service \
/etc/log2ram.conf /etc/log2ram.conf.* /etc/logrotate.d/log2ram
do
pmx_remove_file "$obsolete_path" 2>/dev/null || true
done
rm -rf /etc/systemd/system/log2ram.service.d 2>/dev/null || true
rm -rf /var/log.hdd /tmp/log2ram 2>/dev/null || true
systemctl daemon-reexec >/dev/null 2>&1 || true
systemctl daemon-reload >/dev/null 2>&1 || true
systemctl restart cron >/dev/null 2>&1 || true
msg_ok "$(translate "Previous installation cleaned")"
msg_info "$(translate "Installing Log2RAM from source...")"
if ! command -v git >/dev/null 2>&1; then
apt-get update -qq >/dev/null 2>&1
pmx_install_pkg git
fi
rm -rf /tmp/log2ram 2>/dev/null || true
if ! git clone --depth 1 https://github.com/azlux/log2ram.git /tmp/log2ram >/dev/null 2>>/tmp/log2ram_install.log; then
msg_error "$(translate "Failed to clone log2ram repository. Check /tmp/log2ram_install.log")"
return 1
fi
cd /tmp/log2ram || { msg_error "$(translate "Failed to access log2ram directory")"; return 1; }
if ! bash install.sh >>/tmp/log2ram_install.log 2>&1; then
msg_error "$(translate "Failed to run log2ram installer. Check /tmp/log2ram_install.log")"
return 1
fi
# Drop ACL preservation from the upstream rsync call: some
# /var/log.hdd filesystems reject POSIX ACLs and log2ram write
# exits 23 with `set_acl: Operation not supported`. xattrs stay.
local _l2r_bin
for _l2r_bin in \
"$(command -v log2ram 2>/dev/null)" \
/usr/local/bin/log2ram \
/usr/sbin/log2ram \
/usr/bin/log2ram
do
[[ -n "$_l2r_bin" && -f "$_l2r_bin" ]] || continue
if grep -q 'rsync -aAXv ' "$_l2r_bin" 2>/dev/null; then
cp -a "$_l2r_bin" "${_l2r_bin}.proxmenux.bak"
pmx_edit_file "$_l2r_bin" 's/rsync -aAXv /rsync -aXv --no-acls /g'
fi
pmx_log2ram_drop_stale_journal "$_l2r_bin" || true
break
done
# Size-based rotation for the PBS API logs — the upstream package
# ships no logrotate rule and pvestatd's local-datastore poll fills
# them fast enough to saturate a tmpfs /var/log.
if dpkg-query -W -f='${Status}' proxmox-backup-server 2>/dev/null \
| grep -q 'install ok installed'; then
mkdir -p /var/log/proxmox-backup/api 2>/dev/null || true
pmx_write_file /etc/logrotate.d/proxmox-backup-api <<'EOF'
/var/log/proxmox-backup/api/access.log /var/log/proxmox-backup/api/auth.log {
size 20M
rotate 3
compress
missingok
notifempty
copytruncate
}
EOF
chmod 0644 /etc/logrotate.d/proxmox-backup-api
chown root:root /etc/logrotate.d/proxmox-backup-api
pmx_write_file /etc/cron.hourly/proxmox-backup-logrotate <<'EOF'
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1
EOF
chmod 0755 /etc/cron.hourly/proxmox-backup-logrotate
chown root:root /etc/cron.hourly/proxmox-backup-logrotate
msg_ok "$(translate "PBS API log rotation configured (hourly, size-based)")"
fi
systemctl daemon-reload >/dev/null 2>&1 || true
if [[ -f /etc/log2ram.conf ]] && command -v log2ram >/dev/null 2>&1; then
msg_ok "$(translate "Log2RAM installed successfully")"
else
msg_error "$(translate "Log2RAM installation verification failed. Check /tmp/log2ram_install.log")"
return 1
fi
RAM_SIZE_GB=$(awk '/^MemTotal:/{print int($2/1024/1024)}' /proc/meminfo)
[[ -z "$RAM_SIZE_GB" || "$RAM_SIZE_GB" -eq 0 ]] && RAM_SIZE_GB=4
if (( RAM_SIZE_GB <= 8 )); then
LOG2RAM_SIZE="128M"; CRON_HOURS=1
elif (( RAM_SIZE_GB <= 16 )); then
LOG2RAM_SIZE="256M"; CRON_HOURS=3
else
LOG2RAM_SIZE="512M"; CRON_HOURS=6
fi
msg_ok "$(translate "Detected RAM:") $RAM_SIZE_GB GB — $(translate "Log2RAM size set to:") $LOG2RAM_SIZE"
pmx_edit_file /etc/log2ram.conf "s/^SIZE=.*/SIZE=$LOG2RAM_SIZE/"
LOG2RAM_BIN="$(command -v log2ram || echo /usr/sbin/log2ram)"
pmx_write_file /etc/cron.d/log2ram <<EOF
# Log2RAM periodic sync - Created by ProxMenux
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
0 */$CRON_HOURS * * * root $LOG2RAM_BIN write >/dev/null 2>&1
EOF
chmod 0644 /etc/cron.d/log2ram
chown root:root /etc/cron.d/log2ram
msg_ok "$(translate "Log2RAM write scheduled every") $CRON_HOURS $(translate "hour(s)")"
pmx_write_file /usr/local/bin/log2ram-check.sh <<'EOF'
#!/usr/bin/env bash
# Watch /var/log usage on Log2RAM's tmpfs and act at two thresholds:
# > 80% → vacuum journald down to ~30% of SIZE, then log2ram write
# > 92% → aggressive: journal to ~5%, rotate PBS API logs if present,
# truncate pveproxy/pveam, then log2ram write
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CONF_FILE="/etc/log2ram.conf"
L2R_BIN="$(command -v log2ram || true)"
[[ -z "$L2R_BIN" && -x /usr/sbin/log2ram ]] && L2R_BIN="/usr/sbin/log2ram"
[[ -z "$L2R_BIN" ]] && exit 0
SIZE_MiB="$(grep -E '^SIZE=' "$CONF_FILE" 2>/dev/null | cut -d'=' -f2 | tr -dc '0-9')"
[[ -z "$SIZE_MiB" ]] && SIZE_MiB=128
LIMIT_BYTES=$(( SIZE_MiB * 1024 * 1024 ))
WARN_BYTES=$(( LIMIT_BYTES * 80 / 100 ))
EMERGENCY_BYTES=$(( LIMIT_BYTES * 92 / 100 ))
USED_BYTES="$(df -B1 --output=used /var/log 2>/dev/null | tail -1 | tr -dc '0-9')"
[[ -z "$USED_BYTES" ]] && exit 0
LOCK="/run/log2ram-check.lock"
exec 9>"$LOCK" 2>/dev/null || exit 0
flock -n 9 || exit 0
if (( USED_BYTES > EMERGENCY_BYTES )); then
SAFE_JOURNAL_MB=$(( SIZE_MiB * 5 / 100 ))
[[ "$SAFE_JOURNAL_MB" -lt 16 ]] && SAFE_JOURNAL_MB=16
journalctl --vacuum-size="${SAFE_JOURNAL_MB}M" >/dev/null 2>&1 || true
if [[ -x /usr/sbin/logrotate && -f /etc/logrotate.d/proxmox-backup-api ]]; then
/usr/sbin/logrotate -f /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1 || true
fi
# Only truncate if the file already exists. Creating one from
# this cron path (running as root, default umask) would leave
# it as root:root 644 — pveproxy runs as www-data and would then
# fail to reopen it on the next restart, taking :8006 down.
[ -e /var/log/pveproxy/access.log ] && : > /var/log/pveproxy/access.log 2>/dev/null || true
[ -e /var/log/pveproxy/error.log ] && : > /var/log/pveproxy/error.log 2>/dev/null || true
[ -e /var/log/pveam.log ] && : > /var/log/pveam.log 2>/dev/null || true
"$L2R_BIN" write 2>/dev/null || true
elif (( USED_BYTES > WARN_BYTES )); then
SOFT_JOURNAL_MB=$(( SIZE_MiB * 30 / 100 ))
[[ "$SOFT_JOURNAL_MB" -lt 32 ]] && SOFT_JOURNAL_MB=32
journalctl --vacuum-size="${SOFT_JOURNAL_MB}M" >/dev/null 2>&1 || true
"$L2R_BIN" write 2>/dev/null || true
fi
EOF
chmod +x /usr/local/bin/log2ram-check.sh
pmx_write_file /etc/cron.d/log2ram-auto-sync <<'EOF'
# Log2RAM auto-sync based on /var/log usage - Created by ProxMenux
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
# nice/ionice keep the check off the priority queue for scheduled tasks.
3-59/10 * * * * root nice -n 19 ionice -c 3 /usr/local/bin/log2ram-check.sh >/dev/null 2>&1
EOF
chmod 0644 /etc/cron.d/log2ram-auto-sync
chown root:root /etc/cron.d/log2ram-auto-sync
systemctl restart cron >/dev/null 2>&1 || true
msg_ok "$(translate "Auto-sync enabled when /var/log exceeds 80% of") $LOG2RAM_SIZE"
msg_info "$(translate "Adjusting systemd-journald limits to match Log2RAM size...")"
if [[ -f /etc/systemd/journald.conf ]]; then
cp -n /etc/systemd/journald.conf /etc/systemd/journald.conf.bak.$(date +%Y%m%d-%H%M%S)
fi
SIZE_MB=$(echo "$LOG2RAM_SIZE" | tr -dc '0-9')
USE_MB=$(( SIZE_MB * 55 / 100 ))
KEEP_MB=$(( SIZE_MB * 10 / 100 ))
RUNTIME_MB=$(( SIZE_MB * 25 / 100 ))
[ "$USE_MB" -lt 80 ] && USE_MB=80
[ "$RUNTIME_MB" -lt 32 ] && RUNTIME_MB=32
[ "$KEEP_MB" -lt 8 ] && KEEP_MB=8
# Compose the final file and write it once: keep everything above the
# existing [Journal] section, then our block. Editing then appending
# produced two journal entries for one file, each with half the diff;
# one write shows the whole before/after a sysadmin should read.
{
sed '/^\[Journal\]/,$d' /etc/systemd/journald.conf 2>/dev/null
cat <<EOF
[Journal]
Storage=persistent
SplitMode=none
RateLimitIntervalSec=30s
RateLimitBurst=1000
ForwardToSyslog=no
ForwardToWall=no
Seal=no
Compress=yes
SystemMaxUse=${USE_MB}M
SystemKeepFree=${KEEP_MB}M
RuntimeMaxUse=${RUNTIME_MB}M
# MaxLevelStore=info: required for ProxMenux Monitor log display and Fail2Ban detection.
# Using "warning" silently discards most system logs making date filters useless.
MaxLevelStore=info
MaxLevelSyslog=info
MaxLevelKMsg=warning
MaxLevelConsole=notice
MaxLevelWall=crit
EOF
} | pmx_write_file /etc/systemd/journald.conf
mkdir -p /var/log/pveproxy
chown -R www-data:www-data /var/log/pveproxy
chmod 0750 /var/log/pveproxy
mkdir -p /var/log.hdd/pveproxy
chown -R www-data:www-data /var/log.hdd/pveproxy
chmod 0750 /var/log.hdd/pveproxy
#msg_ok "$(translate "Backup created:") /etc/systemd/journald.conf.bak.$(date +%Y%m%d-%H%M%S)"
msg_ok "$(translate "Journald configuration adjusted to") ${USE_MB}M (Log2RAM ${LOG2RAM_SIZE})"
systemctl daemon-reload >/dev/null 2>&1 || true
if ! pmx_apply_setting "service-enabled:log2ram" "systemctl is-enabled log2ram" \
systemctl enable log2ram; then
msg_error "$(translate "Log2RAM installation verification failed. Check /tmp/log2ram_install.log")"
return 1
fi
pmx_log2ram_setup "$(pmx_log2ram_default_size)" "$(pmx_log2ram_default_hours)" true || return 1
NECESSARY_REBOOT=1
register_tool "log2ram" true "$FUNC_VERSION"
}
+12 -364
View File
@@ -73,6 +73,9 @@ fi
if [[ -f "$LOCAL_SCRIPTS/global/pmx_journal.sh" ]]; then
source "$LOCAL_SCRIPTS/global/pmx_journal.sh"
fi
if [[ -f "$LOCAL_SCRIPTS/global/log2ram_setup.sh" ]]; then
source "$LOCAL_SCRIPTS/global/log2ram_setup.sh"
fi
if [[ -f "$LOCAL_SCRIPTS/post_install/zram_profile_helpers.sh" ]]; then
source "$LOCAL_SCRIPTS/post_install/zram_profile_helpers.sh"
fi
@@ -3287,134 +3290,22 @@ update_pve_appliance_manager() {
_update_existing_log2ram_custom() {
local func_version="$1"
local log2ram_bin=""
local candidate resolved tmp_file
local watch=false
pmx_journal_context "_update_existing_log2ram_custom" "$func_version"
msg_ok "$(translate "Log2RAM already registered — updating to latest configuration")"
for candidate in \
"$(command -v log2ram 2>/dev/null)" \
/usr/local/bin/log2ram \
/usr/sbin/log2ram \
/usr/bin/log2ram
do
[[ -n "$candidate" && -f "$candidate" ]] || continue
resolved="$(readlink -f "$candidate" 2>/dev/null || printf '%s' "$candidate")"
[[ -f "$resolved" ]] || continue
log2ram_bin="$resolved"
break
done
if [[ -z "$log2ram_bin" || ! -f /etc/log2ram.conf ]]; then
msg_error "$(translate "Log2RAM installation verification failed. Check /tmp/log2ram_install.log")"
return 1
fi
if grep -q 'rsync -aAXv ' "$log2ram_bin" 2>/dev/null; then
[[ -e "${log2ram_bin}.proxmenux.bak" ]] || cp -a "$log2ram_bin" "${log2ram_bin}.proxmenux.bak"
sed 's/rsync -aAXv /rsync -aXv --no-acls /g' "$log2ram_bin" | pmx_write_file "$log2ram_bin"
fi
if pmx_log2ram_drop_stale_journal "$log2ram_bin"; then
NECESSARY_REBOOT=1
msg_ok "$(translate "Log2RAM keeps the journal in order from the next reboot")"
fi
if dpkg-query -W -f='${Status}' proxmox-backup-server 2>/dev/null \
| grep -q 'install ok installed'; then
tmp_file="$(mktemp /etc/logrotate.d/.proxmox-backup-api.XXXXXX)" || return 1
cat > "$tmp_file" <<'EOF'
/var/log/proxmox-backup/api/access.log /var/log/proxmox-backup/api/auth.log {
size 20M
rotate 3
compress
missingok
notifempty
copytruncate
}
EOF
chmod 0644 "$tmp_file"
chown root:root "$tmp_file"
pmx_write_file /etc/logrotate.d/proxmox-backup-api < "$tmp_file"
rm -f "$tmp_file"
tmp_file="$(mktemp /etc/cron.hourly/.proxmox-backup-logrotate.XXXXXX)" || return 1
cat > "$tmp_file" <<'EOF'
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1
EOF
chmod 0755 "$tmp_file"
chown root:root "$tmp_file"
pmx_write_file /etc/cron.hourly/proxmox-backup-logrotate < "$tmp_file"
chmod 0755 /etc/cron.hourly/proxmox-backup-logrotate
chown root:root /etc/cron.hourly/proxmox-backup-logrotate
rm -f "$tmp_file"
msg_ok "$(translate "PBS API log rotation configured (hourly, size-based)")"
fi
if [[ -f /usr/local/bin/log2ram-check.sh ]]; then
tmp_file="$(mktemp /usr/local/bin/.log2ram-check.XXXXXX)" || return 1
cat > "$tmp_file" <<'EOF'
#!/usr/bin/env bash
# Watch /var/log usage on Log2RAM's tmpfs and act at two thresholds:
# > 80% → vacuum journald down to ~30% of SIZE, then log2ram write
# > 92% → aggressive: journal to ~5%, rotate PBS API logs if present,
# truncate existing pveproxy/pveam logs, then log2ram write
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CONF_FILE="/etc/log2ram.conf"
L2R_BIN="$(command -v log2ram || true)"
[[ -z "$L2R_BIN" && -x /usr/sbin/log2ram ]] && L2R_BIN="/usr/sbin/log2ram"
[[ -z "$L2R_BIN" ]] && exit 0
SIZE_MiB="$(grep -E '^SIZE=' "$CONF_FILE" 2>/dev/null | cut -d'=' -f2 | tr -dc '0-9')"
[[ -z "$SIZE_MiB" ]] && SIZE_MiB=128
LIMIT_BYTES=$(( SIZE_MiB * 1024 * 1024 ))
WARN_BYTES=$(( LIMIT_BYTES * 80 / 100 ))
EMERGENCY_BYTES=$(( LIMIT_BYTES * 92 / 100 ))
USED_BYTES="$(df -B1 --output=used /var/log 2>/dev/null | tail -1 | tr -dc '0-9')"
[[ -z "$USED_BYTES" ]] && exit 0
LOCK="/run/log2ram-check.lock"
exec 9>"$LOCK" 2>/dev/null || exit 0
flock -n 9 || exit 0
if (( USED_BYTES > EMERGENCY_BYTES )); then
SAFE_JOURNAL_MB=$(( SIZE_MiB * 5 / 100 ))
[[ "$SAFE_JOURNAL_MB" -lt 16 ]] && SAFE_JOURNAL_MB=16
journalctl --vacuum-size="${SAFE_JOURNAL_MB}M" >/dev/null 2>&1 || true
if [[ -x /usr/sbin/logrotate && -f /etc/logrotate.d/proxmox-backup-api ]]; then
/usr/sbin/logrotate -f /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1 || true
fi
[ -e /var/log/pveproxy/access.log ] && : > /var/log/pveproxy/access.log 2>/dev/null || true
[ -e /var/log/pveproxy/error.log ] && : > /var/log/pveproxy/error.log 2>/dev/null || true
[ -e /var/log/pveam.log ] && : > /var/log/pveam.log 2>/dev/null || true
"$L2R_BIN" write 2>/dev/null || true
elif (( USED_BYTES > WARN_BYTES )); then
SOFT_JOURNAL_MB=$(( SIZE_MiB * 30 / 100 ))
[[ "$SOFT_JOURNAL_MB" -lt 32 ]] && SOFT_JOURNAL_MB=32
journalctl --vacuum-size="${SOFT_JOURNAL_MB}M" >/dev/null 2>&1 || true
"$L2R_BIN" write 2>/dev/null || true
fi
EOF
chmod 0755 "$tmp_file"
chown root:root "$tmp_file"
bash -n "$tmp_file" || return 1
pmx_write_file /usr/local/bin/log2ram-check.sh < "$tmp_file"
chmod 0755 /usr/local/bin/log2ram-check.sh
chown root:root /usr/local/bin/log2ram-check.sh
rm -f "$tmp_file"
fi
[[ -f /etc/cron.d/log2ram-auto-sync ]] && watch=true
pmx_log2ram_setup "$(pmx_log2ram_current_size)" "$(pmx_log2ram_current_hours)" "$watch" || return 1
NECESSARY_REBOOT=1
register_tool "log2ram" true "$func_version"
msg_success "$(translate "Log2RAM installation and configuration completed successfully.")"
}
configure_log2ram() {
local FUNC_VERSION="1.8"
local FUNC_VERSION="2.0"
local existing_log2ram_bin=""
local watch=false
pmx_journal_context "configure_log2ram" "$FUNC_VERSION"
# description: Install Log2RAM with a chosen size, sync interval and optional autosync. Updates preserve the size and autosync choice.
@@ -3429,7 +3320,6 @@ configure_log2ram() {
msg_info2 "$(translate "Preparing Log2RAM configuration")"
sleep 1
RAM_SIZE_GB=$(awk '/^MemTotal:/{print int($2/1024/1024)}' /proc/meminfo)
[[ -z "$RAM_SIZE_GB" || "$RAM_SIZE_GB" -eq 0 ]] && RAM_SIZE_GB=4
@@ -3467,254 +3357,12 @@ configure_log2ram() {
"12" "$(translate "Every 12 hours")" OFF \
3>&1 1>&2 2>&3) || return 0
if whiptail --title "Log2RAM" --yesno "$(translate "Enable auto-sync if /var/log exceeds 90% of its size?")" 10 60; then
ENABLE_AUTOSYNC=true
else
ENABLE_AUTOSYNC=false
if whiptail --title "Log2RAM" --yesno "$(translate "Rotate and write /var/log to disk when it passes 85% of its size?")" 10 60; then
watch=true
fi
msg_info "$(translate "Cleaning previous Log2RAM installation...")"
pmx_disable_service log2ram || true
pmx_disable_service log2ram-daily.timer || true
local obsolete_path
for obsolete_path in \
/etc/cron.d/log2ram /etc/cron.d/log2ram-auto-sync \
/etc/cron.hourly/log2ram /etc/cron.daily/log2ram \
/etc/cron.weekly/log2ram /etc/cron.monthly/log2ram \
/usr/local/bin/log2ram-check.sh /usr/local/bin/log2ram /usr/sbin/log2ram \
/etc/systemd/system/log2ram.service \
/etc/systemd/system/log2ram-daily.timer \
/etc/systemd/system/log2ram-daily.service \
/etc/systemd/system/sysinit.target.wants/log2ram.service \
/etc/log2ram.conf /etc/log2ram.conf.* /etc/logrotate.d/log2ram
do
pmx_remove_file "$obsolete_path" 2>/dev/null || true
done
rm -rf /etc/systemd/system/log2ram.service.d 2>/dev/null || true
rm -rf /var/log.hdd /tmp/log2ram 2>/dev/null || true
systemctl daemon-reload >/dev/null 2>&1 || true
systemctl restart cron >/dev/null 2>&1 || true
msg_ok "$(translate "Previous installation cleaned")"
msg_info "$(translate "Installing Log2RAM from GitHub...")"
if ! command -v git >/dev/null 2>&1; then
msg_info "$(translate "Installing required package: git")"
apt-get update -qq >/dev/null 2>&1
pmx_install_pkg git
fi
rm -rf /tmp/log2ram 2>/dev/null || true
if ! git clone --depth 1 https://github.com/azlux/log2ram.git /tmp/log2ram \
>/dev/null 2>>/tmp/log2ram_install.log; then
msg_error "$(translate "Failed to clone log2ram repository. Check /tmp/log2ram_install.log")"
return 1
fi
cd /tmp/log2ram || { msg_error "$(translate "Failed to access log2ram directory")"; return 1; }
if ! bash install.sh >>/tmp/log2ram_install.log 2>&1; then
msg_error "$(translate "Failed to run log2ram installer. Check /tmp/log2ram_install.log")"
return 1
fi
# Drop ACL preservation from the upstream rsync call: some
# /var/log.hdd filesystems reject POSIX ACLs and log2ram write
# exits 23 with `set_acl: Operation not supported`. xattrs stay.
local _l2r_bin
for _l2r_bin in \
"$(command -v log2ram 2>/dev/null)" \
/usr/local/bin/log2ram \
/usr/sbin/log2ram \
/usr/bin/log2ram
do
[[ -n "$_l2r_bin" && -f "$_l2r_bin" ]] || continue
if grep -q 'rsync -aAXv ' "$_l2r_bin" 2>/dev/null; then
cp -a "$_l2r_bin" "${_l2r_bin}.proxmenux.bak"
pmx_edit_file "$_l2r_bin" 's/rsync -aAXv /rsync -aXv --no-acls /g'
fi
pmx_log2ram_drop_stale_journal "$_l2r_bin" || true
break
done
# Size-based rotation for the PBS API logs — the upstream package
# ships no logrotate rule and pvestatd's local-datastore poll fills
# them fast enough to saturate a tmpfs /var/log.
if dpkg-query -W -f='${Status}' proxmox-backup-server 2>/dev/null \
| grep -q 'install ok installed'; then
mkdir -p /var/log/proxmox-backup/api 2>/dev/null || true
pmx_write_file /etc/logrotate.d/proxmox-backup-api <<'EOF'
/var/log/proxmox-backup/api/access.log /var/log/proxmox-backup/api/auth.log {
size 20M
rotate 3
compress
missingok
notifempty
copytruncate
}
EOF
chmod 0644 /etc/logrotate.d/proxmox-backup-api
chown root:root /etc/logrotate.d/proxmox-backup-api
pmx_write_file /etc/cron.hourly/proxmox-backup-logrotate <<'EOF'
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1
EOF
chmod 0755 /etc/cron.hourly/proxmox-backup-logrotate
chown root:root /etc/cron.hourly/proxmox-backup-logrotate
msg_ok "$(translate "PBS API log rotation configured (hourly, size-based)")"
fi
systemctl daemon-reload >/dev/null 2>&1 || true
if [[ -f /etc/log2ram.conf ]] && command -v log2ram >/dev/null 2>&1; then
msg_ok "$(translate "Log2RAM installed successfully")"
else
msg_error "$(translate "Log2RAM installation verification failed. Check /tmp/log2ram_install.log")"
return 1
fi
pmx_edit_file /etc/log2ram.conf "s/^SIZE=.*/SIZE=$LOG2RAM_SIZE/"
LOG2RAM_BIN="$(command -v log2ram || echo /usr/sbin/log2ram)"
pmx_write_file /etc/cron.d/log2ram <<EOF
# Log2RAM periodic sync - Created by ProxMenux
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
0 */$CRON_HOURS * * * root $LOG2RAM_BIN write >/dev/null 2>&1
EOF
chmod 0644 /etc/cron.d/log2ram
chown root:root /etc/cron.d/log2ram
msg_ok "$(translate "Log2RAM write scheduled every") $CRON_HOURS $(translate "hour(s)")"
if [[ "$ENABLE_AUTOSYNC" == true ]]; then
pmx_write_file /usr/local/bin/log2ram-check.sh <<'EOF'
#!/usr/bin/env bash
# Watch /var/log usage on Log2RAM's tmpfs and act at two thresholds:
# > 80% → vacuum journald down to ~30% of SIZE, then log2ram write
# > 92% → aggressive: journal to ~5%, rotate PBS API logs if present,
# truncate existing pveproxy/pveam logs, then log2ram write
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CONF_FILE="/etc/log2ram.conf"
L2R_BIN="$(command -v log2ram || true)"
[[ -z "$L2R_BIN" && -x /usr/sbin/log2ram ]] && L2R_BIN="/usr/sbin/log2ram"
[[ -z "$L2R_BIN" ]] && exit 0
SIZE_MiB="$(grep -E '^SIZE=' "$CONF_FILE" 2>/dev/null | cut -d'=' -f2 | tr -dc '0-9')"
[[ -z "$SIZE_MiB" ]] && SIZE_MiB=128
LIMIT_BYTES=$(( SIZE_MiB * 1024 * 1024 ))
WARN_BYTES=$(( LIMIT_BYTES * 80 / 100 ))
EMERGENCY_BYTES=$(( LIMIT_BYTES * 92 / 100 ))
USED_BYTES="$(df -B1 --output=used /var/log 2>/dev/null | tail -1 | tr -dc '0-9')"
[[ -z "$USED_BYTES" ]] && exit 0
LOCK="/run/log2ram-check.lock"
exec 9>"$LOCK" 2>/dev/null || exit 0
flock -n 9 || exit 0
if (( USED_BYTES > EMERGENCY_BYTES )); then
SAFE_JOURNAL_MB=$(( SIZE_MiB * 5 / 100 ))
[[ "$SAFE_JOURNAL_MB" -lt 16 ]] && SAFE_JOURNAL_MB=16
journalctl --vacuum-size="${SAFE_JOURNAL_MB}M" >/dev/null 2>&1 || true
if [[ -x /usr/sbin/logrotate && -f /etc/logrotate.d/proxmox-backup-api ]]; then
/usr/sbin/logrotate -f /etc/logrotate.d/proxmox-backup-api >/dev/null 2>&1 || true
fi
[ -e /var/log/pveproxy/access.log ] && : > /var/log/pveproxy/access.log 2>/dev/null || true
[ -e /var/log/pveproxy/error.log ] && : > /var/log/pveproxy/error.log 2>/dev/null || true
[ -e /var/log/pveam.log ] && : > /var/log/pveam.log 2>/dev/null || true
"$L2R_BIN" write 2>/dev/null || true
elif (( USED_BYTES > WARN_BYTES )); then
SOFT_JOURNAL_MB=$(( SIZE_MiB * 30 / 100 ))
[[ "$SOFT_JOURNAL_MB" -lt 32 ]] && SOFT_JOURNAL_MB=32
journalctl --vacuum-size="${SOFT_JOURNAL_MB}M" >/dev/null 2>&1 || true
"$L2R_BIN" write 2>/dev/null || true
fi
EOF
chmod +x /usr/local/bin/log2ram-check.sh
pmx_write_file /etc/cron.d/log2ram-auto-sync <<'EOF'
# Log2RAM auto-sync based on /var/log usage - Created by ProxMenux
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
# nice/ionice keep the check off the priority queue for scheduled tasks.
3-59/10 * * * * root nice -n 19 ionice -c 3 /usr/local/bin/log2ram-check.sh >/dev/null 2>&1
EOF
chmod 0644 /etc/cron.d/log2ram-auto-sync
chown root:root /etc/cron.d/log2ram-auto-sync
msg_ok "$(translate "Auto-sync enabled when /var/log exceeds 80% of") $LOG2RAM_SIZE"
else
pmx_remove_file /usr/local/bin/log2ram-check.sh 2>/dev/null || true
pmx_remove_file /etc/cron.d/log2ram-auto-sync 2>/dev/null || true
msg_info2 "$(translate "Auto-sync was not enabled")"
fi
# --- Ajuste de systemd-journald proporcional al tamaño de Log2RAM ---
msg_info "$(translate "Adjusting systemd-journald limits to match Log2RAM size...")"
if [[ -f /etc/systemd/journald.conf ]]; then
cp -n /etc/systemd/journald.conf "/etc/systemd/journald.conf.bak.$(date +%Y%m%d-%H%M%S)"
BAK_OK=$?
fi
SIZE_MB=$(echo "$LOG2RAM_SIZE" | tr -dc '0-9')
# Repartos: 55% persistente / 10% libre / 25% runtime (pisos mínimos)
USE_MB=$(( SIZE_MB * 55 / 100 ))
KEEP_MB=$(( SIZE_MB * 10 / 100 ))
RUNTIME_MB=$(( SIZE_MB * 25 / 100 ))
[ "$USE_MB" -lt 80 ] && USE_MB=80
[ "$RUNTIME_MB" -lt 32 ] && RUNTIME_MB=32
[ "$KEEP_MB" -lt 8 ] && KEEP_MB=8
# Reescribir bloque [Journal] de forma segura
pmx_edit_file /etc/systemd/journald.conf '/^\[Journal\]/,$d' 2>/dev/null || true
pmx_append_file /etc/systemd/journald.conf <<EOF
[Journal]
Storage=persistent
SplitMode=none
RateLimitIntervalSec=30s
RateLimitBurst=1000
ForwardToSyslog=no
ForwardToWall=no
Seal=no
Compress=yes
SystemMaxUse=${USE_MB}M
SystemKeepFree=${KEEP_MB}M
RuntimeMaxUse=${RUNTIME_MB}M
# MaxLevelStore=info: required for ProxMenux Monitor log display and Fail2Ban detection.
# Using "warning" silently discards most system logs making date filters useless.
MaxLevelStore=info
MaxLevelSyslog=info
MaxLevelKMsg=warning
MaxLevelConsole=notice
MaxLevelWall=crit
EOF
[[ "$BAK_OK" = "0" ]] && msg_ok "$(translate "Backup created:") /etc/systemd/journald.conf.bak.$(date +%Y%m%d-%H%M%S)"
msg_ok "$(translate "Journald configuration adjusted to") ${USE_MB}M (Log2RAM ${LOG2RAM_SIZE})"
mkdir -p /var/log/pveproxy
chown -R www-data:www-data /var/log/pveproxy
chmod 0750 /var/log/pveproxy
mkdir -p /var/log.hdd/pveproxy
chown -R www-data:www-data /var/log.hdd/pveproxy
chmod 0750 /var/log.hdd/pveproxy
systemctl restart cron >/dev/null 2>&1 || true
if ! pmx_apply_setting "service-enabled:log2ram" "systemctl is-enabled log2ram" \
systemctl enable log2ram; then
msg_error "$(translate "Log2RAM installation verification failed. Check /tmp/log2ram_install.log")"
return 1
fi
pmx_log2ram_setup "$USER_SIZE" "$CRON_HOURS" "$watch" || return 1
NECESSARY_REBOOT=1
msg_success "$(translate "Log2RAM installation and configuration completed successfully.")"
register_tool "log2ram" true "$FUNC_VERSION"
}
+6 -68
View File
@@ -37,6 +37,9 @@ fi
if [[ -f "$LOCAL_SCRIPTS/global/pmx_journal.sh" ]]; then
source "$LOCAL_SCRIPTS/global/pmx_journal.sh"
fi
if [[ -f "$LOCAL_SCRIPTS/global/log2ram_setup.sh" ]]; then
source "$LOCAL_SCRIPTS/global/log2ram_setup.sh"
fi
if [[ -f "$LOCAL_SCRIPTS/post_install/zram_profile_helpers.sh" ]]; then
source "$LOCAL_SCRIPTS/post_install/zram_profile_helpers.sh"
fi
@@ -735,74 +738,9 @@ uninstall_bashrc_custom() {
################################################################
uninstall_log2ram() {
msg_info "$(translate "Uninstalling log2ram (all versions)...")"
systemctl stop log2ram log2ram-daily.timer log2ram-daily.service >/dev/null 2>&1 || true
systemctl disable log2ram log2ram-daily.timer log2ram-daily.service >/dev/null 2>&1 || true
rm -f /etc/cron.d/log2ram \
/etc/cron.d/log2ram-auto-sync \
/etc/cron.d/log2ram-sync \
/etc/cron.hourly/log2ram \
/etc/cron.daily/log2ram \
/etc/cron.weekly/log2ram \
/etc/cron.monthly/log2ram 2>/dev/null || true
rm -f /usr/local/bin/log2ram-check.sh \
/usr/local/bin/log2ram \
/usr/local/bin/log2ram-sync \
/usr/sbin/log2ram \
/usr/bin/log2ram 2>/dev/null || true
rm -f /etc/systemd/system/log2ram.service \
/etc/systemd/system/log2ram-daily.timer \
/etc/systemd/system/log2ram-daily.service \
/etc/systemd/system/sysinit.target.wants/log2ram.service \
/etc/systemd/system/timers.target.wants/log2ram-daily.timer \
/lib/systemd/system/log2ram.service \
/lib/systemd/system/log2ram-daily.timer \
/lib/systemd/system/log2ram-daily.service 2>/dev/null || true
rm -rf /etc/systemd/system/log2ram.service.d 2>/dev/null || true
rm -f /etc/log2ram.conf \
/etc/log2ram.conf.dpkg-old \
/etc/log2ram.conf.bak \
/etc/log2ram.conf.save 2>/dev/null || true
rm -rf /etc/logrotate.d/log2ram 2>/dev/null || true
if mountpoint -q /var/log 2>/dev/null; then
if [[ -d /var/log.hdd ]]; then
msg_info "$(translate "Preserving logs to /var/log.hdd before unmounting...")"
rsync -a /var/log/ /var/log.hdd/ >/dev/null 2>&1 || true
fi
umount /var/log >/dev/null 2>&1 || true
fi
[[ -d /var/log.hdd ]] && rm -rf /var/log.hdd
[[ -d /tmp/log2ram ]] && rm -rf /tmp/log2ram
[[ -d /var/hdd.log ]] && rm -rf /var/hdd.log
[[ -f /tmp/log2ram_install.log ]] && rm -f /tmp/log2ram_install.log
systemctl daemon-reload >/dev/null 2>&1 || true
systemctl reset-failed >/dev/null 2>&1 || true
systemctl restart cron >/dev/null 2>&1 || true
if dpkg -l 2>/dev/null | grep -q '^ii log2ram'; then
msg_info "$(translate "Purging log2ram apt package...")"
apt-get purge -y log2ram >/dev/null 2>&1 || true
apt-get autoremove -y >/dev/null 2>&1 || true
fi
if [[ -f /etc/log2ram.conf ]] || \
command -v log2ram >/dev/null 2>&1 || \
systemctl list-units --all 2>/dev/null | grep -q log2ram || \
[[ -f /etc/cron.d/log2ram-auto-sync ]]; then
msg_warn "$(translate "Some log2ram files may still exist. Manual cleanup may be required.")"
else
msg_ok "$(translate "log2ram completely removed from system")"
fi
msg_info "$(translate "Uninstalling Log2RAM...")"
pmx_log2ram_remove
msg_ok "$(translate "Log2RAM is removed at the next reboot, after writing /var/log to disk")"
register_tool "log2ram" false
NECESSARY_REBOOT=1
}