diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index ac28aed9..10b4f320 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -17,11 +17,6 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source="./advanced/Scripts/utils.sh" source "${utilsfile}" -# In case we're running at the same time as a system logrotate, use a -# separate logrotate state file to prevent stepping on each other's -# toes. -STATEFILE="/var/lib/logrotate/pihole" - # Determine database location DBFILE=$(getFTLConfigValue "files.database") if [ -z "$DBFILE" ]; then @@ -42,25 +37,6 @@ if [ -z "$WEBFILE" ]; then WEBFILE="/var/log/pihole/webserver.log" fi -# Helper function to handle log rotation for a single file -rotate_log() { - # This function copies x.log over to x.log.1 - # and then empties x.log - # Note that moving the file is not an option, as - # dnsmasq would happily continue writing into the - # moved file (it will have the same file handler) - local logfile="$1" - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Rotating ${logfile} ..." - fi - cp -p "${logfile}" "${logfile}.1" - echo " " > "${logfile}" - chmod 640 "${logfile}" - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Rotated ${logfile} ..." - fi -} - # Helper function to handle log flushing for a single file flush_log() { local logfile="$1" @@ -78,41 +54,23 @@ flush_log() { fi } -if [[ "$*" == *"once"* ]]; then - # Nightly logrotation - if command -v /usr/sbin/logrotate >/dev/null; then - # Logrotate once +# Manual flushing +flush_log "${LOGFILE}" +flush_log "${FTLFILE}" +flush_log "${WEBFILE}" - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Running logrotate ..." - fi - mkdir -p "${STATEFILE%/*}" - /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate - else - # Handle rotation for each log file - rotate_log "${LOGFILE}" - rotate_log "${FTLFILE}" - rotate_log "${WEBFILE}" - fi -else - # Manual flushing - flush_log "${LOGFILE}" - flush_log "${FTLFILE}" - flush_log "${WEBFILE}" - - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..." - fi - - # Stop FTL to make sure it doesn't write to the database while we're deleting data - service pihole-FTL stop - - # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) - deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1") - - # Restart FTL - service pihole-FTL restart - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" - fi +if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..." +fi + +# Stop FTL to make sure it doesn't write to the database while we're deleting data +service pihole-FTL stop + +# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) +deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1") + +# Restart FTL +service pihole-FTL restart +if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" fi diff --git a/advanced/Scripts/piholeLogRotate.sh b/advanced/Scripts/piholeLogRotate.sh new file mode 100755 index 00000000..b7de90ee --- /dev/null +++ b/advanced/Scripts/piholeLogRotate.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Pi-hole: A black hole for Internet advertisements +# (c) 2025 Pi-hole, LLC (https://pi-hole.net) +# Network-wide ad blocking via your own hardware. +# +# Rotate Pi-hole's log file +# +# This file is copyright under the latest version of the EUPL. +# Please see LICENSE file for your rights under this license. + +colfile="/opt/pihole/COL_TABLE" +# shellcheck source="./advanced/Scripts/COL_TABLE" +source ${colfile} + +readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" +utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" +source "${utilsfile}" + +# In case we're running at the same time as a system logrotate, use a +# separate logrotate state file to prevent stepping on each other's +# toes. +STATEFILE="/var/lib/logrotate/pihole" + + +# Determine log file location +LOGFILE=$(getFTLConfigValue "files.log.dnsmasq") +if [ -z "$LOGFILE" ]; then + LOGFILE="/var/log/pihole/pihole.log" +fi +FTLFILE=$(getFTLConfigValue "files.log.ftl") +if [ -z "$FTLFILE" ]; then + FTLFILE="/var/log/pihole/FTL.log" +fi +WEBFILE=$(getFTLConfigValue "files.log.webserver") +if [ -z "$WEBFILE" ]; then + WEBFILE="/var/log/pihole/webserver.log" +fi + +# Helper function to handle log rotation for a single file +rotate_log() { + # This function copies x.log over to x.log.1 + # and then empties x.log + # Note that moving the file is not an option, as + # dnsmasq would happily continue writing into the + # moved file (it will have the same file handler) + local logfile="$1" + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Rotating ${logfile} ..." + fi + cp -p "${logfile}" "${logfile}.1" + echo " " > "${logfile}" + chmod 640 "${logfile}" + if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Rotated ${logfile} ..." + fi +} + +# Nightly logrotation +if command -v /usr/sbin/logrotate >/dev/null; then + # Logrotate once + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Running logrotate ..." + fi + mkdir -p "${STATEFILE%/*}" + /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate +else + # Handle rotation for each log file + rotate_log "${LOGFILE}" + rotate_log "${FTLFILE}" + rotate_log "${WEBFILE}" +fi diff --git a/advanced/Templates/pihole.cron b/advanced/Templates/pihole.cron index c62d31ab..3b71cbff 100644 --- a/advanced/Templates/pihole.cron +++ b/advanced/Templates/pihole.cron @@ -24,7 +24,7 @@ # The flush script will use logrotate if available # parameter "once": logrotate only once (default is twice) # parameter "quiet": don't print messages -00 00 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole flush once quiet +00 00 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole logrotate quiet @reboot root /usr/sbin/logrotate --state /var/lib/logrotate/pihole /etc/pihole/logrotate diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index a4c04158..65464b9e 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -84,7 +84,7 @@ webInterfaceDir="${webroot}/admin" piholeGitUrl="https://github.com/pi-hole/pi-hole.git" PI_HOLE_LOCAL_REPO="/etc/.pihole" # List of pihole scripts, stored in an array -PI_HOLE_FILES=(list piholeDebug piholeLogFlush setupLCD update version gravity uninstall webpage) +PI_HOLE_FILES=(list piholeDebug piholeLogFlush piholeLogRotate setupLCD update version gravity uninstall webpage) # This directory is where the Pi-hole scripts will be installed PI_HOLE_INSTALL_DIR="/opt/pihole" PI_HOLE_CONFIG_DIR="/etc/pihole" diff --git a/manpages/pihole.8 b/manpages/pihole.8 index ac3146ba..191691ee 100644 --- a/manpages/pihole.8 +++ b/manpages/pihole.8 @@ -100,9 +100,12 @@ Available commands and options: -c Include a Pi-hole database integrity check .br -\fB-f, flush\fR +\fB-f, flush\fR [quite] .br - Flush the Pi-hole log + Flush the Pi-hole log and last 24h from the query database +.br + + quite Suppress output .br \fB-r, repair\fR @@ -242,6 +245,14 @@ Available commands and options: verbose Show authentication and status messages .br +\fBlogrotate\fR [quite] +.br + Rotate Pi-hole's log files +.br + + quite Suppress output +.br + .SH "EXAMPLE" Some usage examples diff --git a/pihole b/pihole index e6257b64..4fe09418 100755 --- a/pihole +++ b/pihole @@ -92,6 +92,7 @@ debugFunc() { } flushFunc() { + # unsupported in docker because it requires restarting FTL if [ -n "${DOCKER_VERSION}" ]; then unsupportedFunc else @@ -109,6 +110,11 @@ arpFunc() { exit 0 } +logrotateFunc() { + "${PI_HOLE_SCRIPT_DIR}"/piholeLogRotate.sh "$@" + exit 0 +} + networkFlush() { shift "${PI_HOLE_SCRIPT_DIR}"/piholeNetworkFlush.sh "$@" @@ -506,7 +512,8 @@ Debugging Options: -d, debug Start a debugging session Add '-c' or '--check-database' to include a Pi-hole database integrity check Add '-a' to automatically upload the log to tricorder.pi-hole.net - -f, flush Flush the Pi-hole log + -f, flush Flush the Pi-hole logs and last 24h from the query database + Add 'quiet' to suppress output messages -r, repair Repair Pi-hole subsystems -t, tail [arg] View the live output of the Pi-hole log. Add an optional argument to filter the log @@ -539,7 +546,9 @@ Options: checkout Switch Pi-hole subsystems to a different GitHub branch Add '-h' for more info on checkout usage networkflush Flush information stored in Pi-hole's network tables - Add '--arp' to additionally flush the ARP table "; + Add '--arp' to additionally flush the ARP table + logrotate Rotate Pi-hole's log files + Add 'quiet' to suppress output messages"; exit 0 } @@ -582,6 +591,7 @@ case "${1}" in "arpflush" ) need_root=true;; # Deprecated, use networkflush instead "networkflush" ) need_root=true;; "-t" | "tail" ) need_root=true;; + "logrotate" ) need_root=true;; * ) helpFunc;; esac @@ -617,5 +627,6 @@ case "${1}" in "arpflush" ) arpFunc "$@";; # Deprecated, use networkflush instead "networkflush" ) networkFlush "$@";; "-t" | "tail" ) tailFunc "$2";; + "logrotate" ) logrotateFunc "$@";; * ) helpFunc;; esac