#!/bin/bash # # Copyright (c) Authors: https://www.armbian.com/authors # # This file is licensed under the terms of the GNU General Public # License version 2. This program is licensed "as is" without any # warranty of any kind, whether express or implied. SIZE=50M USE_RSYNC=true ENABLED=false [ -f /etc/default/armbian-ramlog ] && . /etc/default/armbian-ramlog [ "$ENABLED" != true ] && exit 0 # Never touch anything below here. Only edit /etc/default/armbian-ramlog HDD_LOG=/var/log.hdd RAM_LOG=/var/log LOG2RAM_LOG="${HDD_LOG}/armbian-ramlog.log" LOG_OUTPUT="tee -a $LOG2RAM_LOG" isSafe () { [ -d $HDD_LOG ] || (echo "ERROR: $HDD_LOG doesn't exist! Can't sync." >&2 ; exit 1) NoCache=$(command -v nocache 2>/dev/null) } RecreateLogs (){ # in case of crash those services don't start if there are no dirs & logs check_if_installed apache2 && [ ! -d /var/log/apache2 ] && mkdir -p /var/log/apache2 check_if_installed cron-apt && [ ! -d /var/log/cron-apt ] && \ (mkdir -p /var/log/cron-apt ; touch /var/log/cron-apt/log) check_if_installed proftpd-basic && [ ! -d /var/log/proftpd ] && \ (mkdir -p /var/log/proftpd ; touch /var/log/proftpd/controls.log) check_if_installed nginx && [ ! -d /var/log/nginx ] && \ (mkdir -p /var/log/nginx ; touch /var/log/nginx/access.log ; touch /var/log/nginx/error.log) check_if_installed lighttpd && [ ! -d /var/log/lighttpd ] && \ (mkdir -p /var/log/lighttpd ; touch /var/log/lighttpd/access.log ; touch /var/log/lighttpd/error.log) check_if_installed samba && [ ! -d /var/log/samba ] && mkdir -p /var/log/samba check_if_installed unattended-upgrades && [ ! -d /var/log/unattended-upgrades ] && mkdir -p /var/log/unattended-upgrades return 0 } syncToDisk () { isSafe echo -e "\n\n$(date): Syncing logs to storage\n" | $LOG_OUTPUT if [ "$USE_RSYNC" = true ]; then ${NoCache} rsync -aXWv \ --exclude "lost+found" --exclude armbian-ramlog.log \ --exclude 'journal*' --one-file-system \ --links \ ${XTRA_RSYNC_TO[@]+"${XTRA_RSYNC_TO[@]}"} \ $RAM_LOG/ $HDD_LOG/ 2>&1 | $LOG_OUTPUT else rm -f $RAM_LOG/journal # linked journal cannot copied onto itself, it will be re-created below ${NoCache} cp -rfup $RAM_LOG -T $HDD_LOG 2>&1 | $LOG_OUTPUT fi if [ ! -L $RAM_LOG/journal ] && [ -d $RAM_LOG/journal ]; then # move persistent journal to disk systemctl stop systemd-journald # journal folder can be in use if [ -d $HDD_LOG/journal ]; then # optional backup for diagnosis mv $HDD_LOG/journal $HDD_LOG/journal-$(date +"%Y%M%d-%T") fi mv $RAM_LOG/journal $HDD_LOG/journal systemctl start systemd-journald fi if [ ! -L $RAM_LOG/journal ] && [ -d $HDD_LOG/journal ]; then # link persistent journal if applicable ln -s ${HDD_LOG}/journal ${RAM_LOG}/ fi if [ -z "`grep ^Storage=volatile /etc/systemd/journald.conf`" ] ;then # flush to disk when applicable journalctl --flush # this will flush to persistent log journalctl --relinquish-var # restart volatile logging fi sync / } syncFromDisk () { isSafe echo -e "\n\n$(date): Loading logs from storage\n" | $LOG_OUTPUT if [ "$USE_RSYNC" = true ]; then ${NoCache} rsync -aXWv --delete \ --exclude "lost+found" --exclude armbian-ramlog.log \ --exclude '*.gz' --exclude '*.xz' --exclude='*.[0-9]' \ --links \ --exclude 'journal*' --one-file-system \ ${XTRA_RSYNC_FROM[@]+"${XTRA_RSYNC_FROM[@]}"} \ $HDD_LOG/ $RAM_LOG/ 2>&1 | $LOG_OUTPUT else ${NoCache} find $HDD_LOG/* -maxdepth 1 -type f -not \( -name '*.[0-9]' -or -name '*.xz*' -or -name '*.gz' -or -name 'journal*' \) | xargs cp -ut $RAM_LOG/ fi if [ ! -L $RAM_LOG/journal ] && [ -d $HDD_LOG/journal ]; then # link persistent journal if applicable ln -s ${HDD_LOG}/journal ${RAM_LOG}/ fi sync / } check_if_installed () { local DPKG_Status="$(dpkg -s "$1" 2>/dev/null | awk -F": " '/^Status/ {print $2}')" if [[ "X${DPKG_Status}" = "X" || "${DPKG_Status}" = *deinstall* ]]; then return 1 else return 0 fi } case "$1" in start) [ -d $HDD_LOG ] || mkdir -p $HDD_LOG mount --bind $RAM_LOG $HDD_LOG mount --make-private $HDD_LOG # Check whether zram device is available or we need to use tmpfs LOG_TYPE="tmpfs" for rd in /dev/zram*; do if [[ "$(e2label $rd)" == "log2ram" ]]; then LOG_TYPE="zram" break fi done case $LOG_TYPE in zram) echo -e "Mounting $rd as $RAM_LOG \c" | $LOG_OUTPUT mount -o discard $rd $RAM_LOG 2>&1 | $LOG_OUTPUT ;; tmpfs) echo -e "Setting up $RAM_LOG as tmpfs \c" | $LOG_OUTPUT mount -t tmpfs -o nosuid,noexec,nodev,mode=0755,size=$SIZE armbian-ramlog $RAM_LOG 2>&1 | $LOG_OUTPUT ;; esac syncFromDisk RecreateLogs ;; stop) syncToDisk umount -l $RAM_LOG umount -l $HDD_LOG ;; write) syncToDisk ;; postrotate) cd /var/log.hdd/ find . -type f -print | grep -E -v "(\.gz|\.xz|\.[0-9]|armbian-ramlog)" | while IFS= read -r file do dest="/var/log/$file" cat $file > $dest done ;; *) echo "Usage: ${0##*/} {start|stop|write}" >&2 exit 1 ;; esac