Compare commits

...

48 Commits

Author SHA1 Message Date
Adam Warner 5ed52554d7 Move unattended check to the top of the script - exit early if /etc/pihole/pihole.toml file is not found,
CodeQL / Analyze (pull_request) Has been cancelled
Test Supported Distributions / smoke-tests (pull_request) Has been cancelled
Test Supported Distributions / distro-test (centos_10) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (centos_9) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (debian_11) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (debian_12) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (fedora_40) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (fedora_41) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (fedora_42) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (ubuntu_20) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (ubuntu_22) (pull_request) Has been cancelled
Test Supported Distributions / distro-test (ubuntu_24) (pull_request) Has been cancelled
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-08-11 14:55:39 +01:00
yubiuser 75286a1626 Bump tox from 4.28.3 to 4.28.4 in /test in the python-dependencies group (#6371) 2025-08-02 12:56:30 +02:00
dependabot[bot] 9bc17a1f2b Bump tox from 4.28.3 to 4.28.4 in /test in the python-dependencies group
Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox).


Updates `tox` from 4.28.3 to 4.28.4
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.28.3...4.28.4)

---
updated-dependencies:
- dependency-name: tox
  dependency-version: 4.28.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-02 10:52:42 +00:00
yubiuser 86850e9020 Add "setpassword" to pihole Bash completion (#6369) 2025-07-31 19:06:45 +02:00
deHakkelaar d4562a1deb Add "setpassword" to pihole Bash completion
Its missing.
After:

```
$ sudo pihole
allow          arpflush       disable        logging        reloadlists    tail           version
allow-regex    checkout       enable         query          repair         uninstall      wildcard
allow-wild     debug          flush          regex          setpassword    updateGravity
api            deny           help           reloaddns      status         updatePihole
```

Signed-off-by: deHakkelaar <deHakkelaar@users.noreply.github.com>
2025-07-31 18:03:43 +02:00
Adam Warner 62ccfc77de Explicitly check for the existence of FTL binary before attempting to stop it. Prevents warning message on fresh installs (#6364) 2025-07-28 15:56:42 +01:00
Dominik 0df3b41ca0 Do not call pihole-FTL --config interactively (#6368) 2025-07-27 20:25:31 +02:00
DL6ER 5cb601200c Use non-interactive shell in utils.sh:getFTLConfigValue to avoid colored output
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-07-26 21:54:25 +02:00
Adam Warner 342c8b693b Revert "pihole api - use keepalive for curl queries" (#6367) 2025-07-26 19:12:46 +01:00
Adam Warner 24d8754033 Revert "pihole api - use keepalive for curl queries" 2025-07-26 12:35:02 +01:00
yubiuser 966e466c9e Bump tox from 4.27.0 to 4.28.3 in /test in the python-dependencies group (#6366) 2025-07-26 12:43:27 +02:00
dependabot[bot] 37ec67e9a3 Bump tox from 4.27.0 to 4.28.3 in /test in the python-dependencies group
Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox).


Updates `tox` from 4.27.0 to 4.28.3
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.27.0...4.28.3)

---
updated-dependencies:
- dependency-name: tox
  dependency-version: 4.28.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-26 10:36:36 +00:00
Adam Warner 364ba99b1f Update automated install/basic-install.sh
Co-authored-by: yubiuser <github@yubiuser.dev>
Signed-off-by: Adam Warner <github@adamwarner.co.uk>
2025-07-26 10:56:21 +01:00
Adam Warner 9252e90bd6 Check for the existence of the FTL binary before stopping the service
This prevents errors on fresh installs where the FTL binary does not exist yet.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-07-26 10:31:58 +01:00
Adam Warner ae0fef4626 pihole api - use keepalive for curl queries (#6365) 2025-07-26 10:22:16 +01:00
Rob Gill 5b4a7b8b74 pihole api - use keepalive for curl queries
Adds the keepalive header to all curl requests

This reduces session establishment time across the multiple

requests necessary to authenticate, obtain response and log out

Signed-off-by: Rob Gill <rrobgill@protonmail.com>
2025-07-26 18:48:32 +10:00
Dan Schaper a9680db218 Use 'true'/'false' strings instead of 0/1 integers for boolean root user check in pihole command (#6351) 2025-07-23 09:16:15 -07:00
Christian König 7aa57e154e Group functions
Signed-off-by: Christian König <github@yubiuser.dev>
2025-07-23 08:23:09 +02:00
Christian König 05f4ae7719 Invert need_root logic and check if set/unset
Signed-off-by: Christian König <github@yubiuser.dev>
Co-authored-by: Dan Schaper <dan.schaper@pi-hole.net>
2025-07-23 08:09:26 +02:00
Dan Schaper 29b6252935 Fix gravity user permission checking and fix error on pihole-FTL --config failures (#6352) 2025-07-22 15:27:07 -07:00
Dan Schaper f324d4cc7d Separate network flush and arp table flush functions (#6319)
This PR updates the function flushing the network tables and the ARP table. It separates the two, renaming the whole function to networkflush and makes flushing ARP optional by appending --arp. Deletion of the network table is now done via FTL's /action/flush/arp endpoint.

Documentation: https://github.com/pi-hole/docs/pull/1253
Related PR in the FTL repo: https://github.com/pi-hole/FTL/pull/2541
2025-07-22 15:20:50 -07:00
yubiuser 310f0711fa Group evaluations
Co-authored-by: Dan Schaper <dan.schaper@pi-hole.net>
Signed-off-by: yubiuser <github@yubiuser.dev>
2025-07-22 12:52:43 +02:00
Christian König 9580dc6560 Improve setFTLConfigValue function
Signed-off-by: Christian König <github@yubiuser.dev>
2025-07-22 12:50:42 +02:00
Christian König 70e317f373 Revert https://github.com/pi-hole/pi-hole/pull/6345
Signed-off-by: Christian König <github@yubiuser.dev>
2025-07-22 12:50:42 +02:00
Christian König 285b3c37f9 Tweak fluash ARP function
Signed-off-by: Christian König <github@yubiuser.dev>
2025-07-22 12:45:22 +02:00
Dan Schaper 41f6738e97 Update man page - remove "reconfigure" option (#6361) 2025-07-21 13:57:51 -07:00
RD WebDesign 22e6ff2cdf Update man page - remove "reconfigure" option
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-07-21 16:15:25 -03:00
Dan Schaper be36432f24 Speed up pihole api (#6336) 2025-07-21 10:51:25 -07:00
Dan Schaper 4bea9a1d12 Use RTMIN value provided by FTL when possible (#6358)
In some cases `kill -RTMIN` can send incorrect signal value to the FTL causing it to terminate instead of performing lists reload.
https://github.com/pi-hole/FTL/issues/2573
2025-07-20 18:06:00 -07:00
Dan Schaper 35ce3580e5 Reduce pihole --query jq calls (#6334) 2025-07-20 18:02:45 -07:00
Dan Schaper 90eb5778ca Re-order authentication errors in verbose mode (#6338) 2025-07-20 17:46:07 -07:00
Dan Schaper c0539a4fb0 Remove netcat from the list of dependencies (#6343) 2025-07-20 17:44:04 -07:00
Jack'lul da85a7a2a7 Use RTMIN value provided by FTL when possible
Signed-off-by: Jack'lul <jacklulcat@gmail.com>
2025-07-18 23:13:19 +02:00
Christian König 3c52ce98d4 Revert https://github.com/pi-hole/pi-hole/pull/6312
Signed-off-by: Christian König <github@yubiuser.dev>
2025-07-16 13:50:37 +02:00
Dan Schaper ae048201a2 Remove readonly from list.sh to avoid errors (#6349) 2025-07-14 21:10:53 -07:00
RD WebDesign dad27f8d06 Remove readonly from list.sh to avoid errors
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-07-14 21:20:39 -03:00
Dan Schaper c0b512be60 Sync master back into development (#6348) 2025-07-14 14:45:31 -07:00
Adam Warner cef7fd4b02 Pi-hole core 6.1.4 (#6347) 2025-07-14 22:15:50 +01:00
Adam Warner c09da77e2b Fix pihole api command by not setting the some variabes as readonly (#6346) 2025-07-14 22:09:27 +01:00
Adam Warner 18e8396a44 Fix issue where web interface cannot run gravity (#6345) 2025-07-14 22:05:18 +01:00
Adam Warner 1bef0415db bare minimum first past fix for pihoe api command not working due to attempting to re-set readony variabes PI_HOE_SCRIPT_DIR and utisfie.
Can't compain about them being readony if they're.. not.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-07-14 22:02:02 +01:00
Adam Warner d6a83baf4f Allow non-root access for updateGravity command
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-07-14 21:38:59 +01:00
Dan Schaper 605ff8183a Sync master back into development (#6341) 2025-07-14 11:45:03 -07:00
darkexplosiveqwx e231107e81 Remove netcat from the list of dependencies
Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com>
2025-07-14 20:18:18 +02:00
Christian König 71501e15e5 Re-order authentication errors in verbose mode
Signed-off-by: Christian König <github@yubiuser.dev>
2025-07-13 22:16:40 +02:00
Rob Gill 0187087da0 Speed up pihole --api
Get session authentication information via single jq operation,
setting defaults if no data returned.

Simplify jq test for valid JSON data

Signed-off-by: Rob Gill <rrobgill@protonmail.com>
2025-07-14 05:44:46 +10:00
Rob Gill 05ad3d7155 Update advanced/Scripts/query.sh
Co-authored-by: yubiuser <github@yubiuser.dev>
Signed-off-by: Rob Gill <rrobgill@protonmail.com>
2025-07-12 22:25:22 +00:00
Rob Gill ea8272d7d4 speed up pihole --query
Count list and gravity matches using jq in a single step.

Use jq's map to simplify list processing, eliminating intermediate
jsons.

Eliminate while loop for each lists's final output and formatting.

Signed-off-by: Rob Gill <rrobgill@protonmail.com>
2025-07-12 14:25:17 +10:00
11 changed files with 231 additions and 195 deletions
+24 -13
View File
@@ -150,7 +150,6 @@ LoginAPI() {
# Try to login again until the session is valid # Try to login again until the session is valid
while [ ! "${validSession}" = true ] ; do while [ ! "${validSession}" = true ] ; do
echo "Authentication failed. Please enter your Pi-hole password"
# Print the error message if there is one # Print the error message if there is one
if [ ! "${sessionError}" = "null" ] && [ "${1}" = "verbose" ]; then if [ ! "${sessionError}" = "null" ] && [ "${1}" = "verbose" ]; then
@@ -161,6 +160,14 @@ LoginAPI() {
echo "Error: ${sessionMessage}" echo "Error: ${sessionMessage}"
fi fi
if [ "${1}" = "verbose" ]; then
# If we are not in verbose mode, no need to print the error message again
echo "Please enter your Pi-hole password"
else
echo "Authentication failed. Please enter your Pi-hole password"
fi
# secretly read the password # secretly read the password
secretRead; printf '\n' secretRead; printf '\n'
@@ -183,13 +190,20 @@ Authentication() {
echo "No response from FTL server. Please check connectivity" echo "No response from FTL server. Please check connectivity"
exit 1 exit 1
fi fi
# obtain validity, session ID and sessionMessage from session response
validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null)
SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null)
sessionMessage=$(echo "${sessionResponse}"| jq --raw-output .session.message 2>/dev/null)
# obtain the error message from the session response # obtain validity, session ID, sessionMessage and error message from
sessionError=$(echo "${sessionResponse}"| jq --raw-output .error.message 2>/dev/null) # session response, apply default values if none returned
result=$(echo "${sessionResponse}" | jq -r '
(.session.valid // false),
(.session.sid // null),
(.session.message // null),
(.error.message // null)
' 2>/dev/null)
validSession=$(echo "${result}" | sed -n '1p')
SID=$(echo "${result}" | sed -n '2p')
sessionMessage=$(echo "${result}" | sed -n '3p')
sessionError=$(echo "${result}" | sed -n '4p')
if [ "${1}" = "verbose" ]; then if [ "${1}" = "verbose" ]; then
if [ "${validSession}" = true ]; then if [ "${validSession}" = true ]; then
@@ -353,12 +367,9 @@ apiFunc() {
if [ "${verbosity}" = "verbose" ]; then if [ "${verbosity}" = "verbose" ]; then
echo "Data:" echo "Data:"
fi fi
# Attempt to print the data with jq, if it is not valid JSON, or not installed
if command -v jq >/dev/null && echo "${data}" | jq . >/dev/null 2>&1; then # then print the plain text.
echo "${data}" | jq . echo "${data}" | jq . 2>/dev/null || echo "${data}"
else
echo "${data}"
fi
# Delete the session # Delete the session
LogoutAPI "${verbosity}" LogoutAPI "${verbosity}"
+3 -3
View File
@@ -9,12 +9,12 @@
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" PI_HOLE_SCRIPT_DIR="/opt/pihole"
readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source="./advanced/Scripts/utils.sh" # shellcheck source="./advanced/Scripts/utils.sh"
source "${utilsfile}" source "${utilsfile}"
readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" apifile="${PI_HOLE_SCRIPT_DIR}/api.sh"
# shellcheck source="./advanced/Scripts/api.sh" # shellcheck source="./advanced/Scripts/api.sh"
source "${apifile}" source "${apifile}"
-83
View File
@@ -1,83 +0,0 @@
#!/usr/bin/env bash
# Pi-hole: A black hole for Internet advertisements
# (c) 2019 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# ARP table interaction
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then
# shellcheck source="./advanced/Scripts/COL_TABLE"
source ${coltable}
fi
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source=./advanced/Scripts/utils.sh
source "${utilsfile}"
# Determine database location
DBFILE=$(getFTLConfigValue "files.database")
if [ -z "$DBFILE" ]; then
DBFILE="/etc/pihole/pihole-FTL.db"
fi
flushARP(){
local output
if [[ "${args[1]}" != "quiet" ]]; then
echo -ne " ${INFO} Flushing network table ..."
fi
# Stop FTL to prevent database access
if ! output=$(service pihole-FTL stop 2>&1); then
echo -e "${OVER} ${CROSS} Failed to stop FTL"
echo " Output: ${output}"
return 1
fi
# Truncate network_addresses table in pihole-FTL.db
# This needs to be done before we can truncate the network table due to
# foreign key constraints
if ! output=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM network_addresses" 2>&1); then
echo -e "${OVER} ${CROSS} Failed to truncate network_addresses table"
echo " Database location: ${DBFILE}"
echo " Output: ${output}"
return 1
fi
# Truncate network table in pihole-FTL.db
if ! output=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM network" 2>&1); then
echo -e "${OVER} ${CROSS} Failed to truncate network table"
echo " Database location: ${DBFILE}"
echo " Output: ${output}"
return 1
fi
# Flush ARP cache of the host
if ! output=$(ip -s -s neigh flush all 2>&1); then
echo -e "${OVER} ${CROSS} Failed to flush ARP cache"
echo " Output: ${output}"
return 1
fi
# Start FTL again
if ! output=$(service pihole-FTL restart 2>&1); then
echo -e "${OVER} ${CROSS} Failed to restart FTL"
echo " Output: ${output}"
return 1
fi
if [[ "${args[1]}" != "quiet" ]]; then
echo -e "${OVER} ${TICK} Flushed network table"
fi
}
args=("$@")
case "${args[0]}" in
"arpflush" ) flushARP;;
esac
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env bash
# Pi-hole: A black hole for Internet advertisements
# (c) 2019 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# Network table flush
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then
# shellcheck source="./advanced/Scripts/COL_TABLE"
source ${coltable}
fi
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source=./advanced/Scripts/utils.sh
source "${utilsfile}"
# Source api functions
# shellcheck source="./advanced/Scripts/api.sh"
. "${PI_HOLE_SCRIPT_DIR}/api.sh"
flushNetwork(){
local output
echo -ne " ${INFO} Flushing network table ..."
local data status error
# Authenticate with FTL
LoginAPI
# send query again
data=$(PostFTLData "action/flush/network" "" "status")
# Separate the status from the data
status=$(printf %s "${data#"${data%???}"}")
data=$(printf %s "${data%???}")
# If there is an .error object in the returned data, display it
local error
error=$(jq --compact-output <<< "${data}" '.error')
if [[ $error != "null" && $error != "" ]]; then
echo -e "${OVER} ${CROSS} Failed to flush the network table:"
echo -e " $(jq <<< "${data}" '.error')"
LogoutAPI
exit 1
elif [[ "${status}" == "200" ]]; then
echo -e "${OVER} ${TICK} Flushed network table"
fi
# Delete session
LogoutAPI
}
flushArp(){
# Flush ARP cache of the host
if ! output=$(ip -s -s neigh flush all 2>&1); then
echo -e "${OVER} ${CROSS} Failed to flush ARP cache"
echo " Output: ${output}"
return 1
fi
}
# Process all options (if present)
while [ "$#" -gt 0 ]; do
case "$1" in
"--arp" ) doARP=true ;;
esac
shift
done
flushNetwork
if [[ "${doARP}" == true ]]; then
echo -ne " ${INFO} Flushing ARP cache"
if flushArp; then
echo -e "${OVER} ${TICK} Flushed ARP cache"
fi
fi
+14 -24
View File
@@ -37,19 +37,16 @@ Options:
} }
GenerateOutput() { GenerateOutput() {
local data gravity_data lists_data num_gravity num_lists search_type_str local counts data num_gravity num_lists search_type_str
local gravity_data_csv lists_data_csv line current_domain url type color local gravity_data_csv lists_data_csv line url type color
data="${1}" data="${1}"
# construct a new json for the list results where each object contains the domain and the related type # Get count of list and gravity matches
lists_data=$(printf %s "${data}" | jq '.search.domains | [.[] | {domain: .domain, type: .type}]') # Use JQ to count number of entries in lists and gravity
# (output is number of list matches then number of gravity matches)
# construct a new json for the gravity results where each object contains the adlist URL and the related domains counts=$(printf %s "${data}" | jq --raw-output '(.search.domains | length), (.search.gravity | group_by(.address,.type) | length)')
gravity_data=$(printf %s "${data}" | jq '.search.gravity | group_by(.address,.type) | map({ address: (.[0].address), type: (.[0].type), domains: [.[] | .domain] })') num_lists=$(echo "$counts" | sed -n '1p')
num_gravity=$(echo "$counts" | sed -n '2p')
# number of objects in each json
num_gravity=$(printf %s "${gravity_data}" | jq length)
num_lists=$(printf %s "${lists_data}" | jq length)
if [ "${partial}" = true ]; then if [ "${partial}" = true ]; then
search_type_str="partially" search_type_str="partially"
@@ -62,7 +59,7 @@ GenerateOutput() {
if [ "${num_lists}" -gt 0 ]; then if [ "${num_lists}" -gt 0 ]; then
# Convert the data to a csv, each line is a "domain,type" string # Convert the data to a csv, each line is a "domain,type" string
# not using jq's @csv here as it quotes each value individually # not using jq's @csv here as it quotes each value individually
lists_data_csv=$(printf %s "${lists_data}" | jq --raw-output '.[] | [.domain, .type] | join(",")') lists_data_csv=$(printf %s "${data}" | jq --raw-output '.search.domains | map([.domain, .type] | join(",")) | join("\n")')
# Generate output for each csv line, separating line in a domain and type substring at the ',' # Generate output for each csv line, separating line in a domain and type substring at the ','
echo "${lists_data_csv}" | while read -r line; do echo "${lists_data_csv}" | while read -r line; do
@@ -71,11 +68,11 @@ GenerateOutput() {
fi fi
# Results from gravity # Results from gravity
printf "%s\n\n" "Found ${num_gravity} adlists ${search_type_str} matching '${COL_BLUE}${domain}${COL_NC}'." printf "%s\n\n" "Found ${num_gravity} lists ${search_type_str} matching '${COL_BLUE}${domain}${COL_NC}'."
if [ "${num_gravity}" -gt 0 ]; then if [ "${num_gravity}" -gt 0 ]; then
# Convert the data to a csv, each line is a "URL,domain,domain,...." string # Convert the data to a csv, each line is a "URL,type,domain,domain,...." string
# not using jq's @csv here as it quotes each value individually # not using jq's @csv here as it quotes each value individually
gravity_data_csv=$(printf %s "${gravity_data}" | jq --raw-output '.[] | [.address, .type, .domains[]] | join(",")') gravity_data_csv=$(printf %s "${data}" | jq --raw-output '.search.gravity | group_by(.address,.type) | map([.[0].address, .[0].type, (.[] | .domain)] | join(",")) | join("\n")')
# Generate line-by-line output for each csv line # Generate line-by-line output for each csv line
echo "${gravity_data_csv}" | while read -r line; do echo "${gravity_data_csv}" | while read -r line; do
@@ -97,15 +94,8 @@ GenerateOutput() {
# cut off type, leaving "domain,domain,...." # cut off type, leaving "domain,domain,...."
line=${line#*,} line=${line#*,}
# print each domain and remove it from the string until nothing is left # Replace commas with newlines and format output
while [ ${#line} -gt 0 ]; do echo "${line}" | sed 's/,/\n/g' | sed "s/^/ - ${COL_GREEN}/" | sed "s/$/${COL_NC}/"
current_domain=${line%%,*}
printf ' - %s\n' "${COL_GREEN}${current_domain}${COL_NC}"
# we need to remove the current_domain and the comma in two steps because
# the last domain won't have a trailing comma and the while loop wouldn't exit
line=${line#"${current_domain}"}
line=${line#,}
done
printf "\n\n" printf "\n\n"
done done
fi fi
+16 -6
View File
@@ -73,7 +73,9 @@ getFTLPID() {
# Example getFTLConfigValue dns.piholePTR # Example getFTLConfigValue dns.piholePTR
####################### #######################
getFTLConfigValue(){ getFTLConfigValue(){
pihole-FTL --config -q "${1}" # Pipe to cat to avoid pihole-FTL assuming this is an interactive command
# returning colored output.
pihole-FTL --config -q "${1}" | cat
} }
####################### #######################
@@ -86,9 +88,17 @@ getFTLConfigValue(){
# setFTLConfigValue dns.upstreams '[ "8.8.8.8" , "8.8.4.4" ]' # setFTLConfigValue dns.upstreams '[ "8.8.8.8" , "8.8.4.4" ]'
####################### #######################
setFTLConfigValue(){ setFTLConfigValue(){
pihole-FTL --config "${1}" "${2}" >/dev/null local err
if [ $? -eq 5 ]; then { pihole-FTL --config "${1}" "${2}" >/dev/null; err="$?"; } || true
printf " %s %s set by environment variable. Please unset it to use this function\n" "${CROSS}" "${1}"
exit 5 case $err in
fi 0) ;;
5)
# FTL returns 5 if the value was set by an environment variable and is therefore read-only
printf " %s %s set by environment variable. Please unset it to use this function\n" "${CROSS}" "${1}";
exit 5;;
*)
printf " %s Failed to set %s. Try with sudo power\n" "${CROSS}" "${1}"
exit 1
esac
} }
+8 -4
View File
@@ -1,5 +1,5 @@
_pihole() { _pihole() {
local cur prev opts opts_checkout opts_debug opts_logging opts_query opts_update opts_version local cur prev opts opts_lists opts_checkout opts_debug opts_logging opts_query opts_update opts_networkflush
COMPREPLY=() COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}" cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}" prev="${COMP_WORDS[COMP_CWORD-1]}"
@@ -7,7 +7,7 @@ _pihole() {
case "${prev}" in case "${prev}" in
"pihole") "pihole")
opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard arpflush api" opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists setpassword status tail uninstall updateGravity updatePihole version wildcard networkflush api"
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
;; ;;
"allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild") "allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild")
@@ -34,9 +34,13 @@ _pihole() {
opts_update="--check-only" opts_update="--check-only"
COMPREPLY=( $(compgen -W "${opts_update}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts_update}" -- ${cur}) )
;; ;;
"core"|"admin"|"ftl") "networkflush")
opts_networkflush="--arp"
COMPREPLY=( $(compgen -W "${opts_networkflush}" -- ${cur}) )
;;
"core"|"web"|"ftl")
if [[ "$prev2" == "checkout" ]]; then if [[ "$prev2" == "checkout" ]]; then
opts_checkout="master dev" opts_checkout="master development"
COMPREPLY=( $(compgen -W "${opts_checkout}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts_checkout}" -- ${cur}) )
else else
return 1 return 1
+24 -15
View File
@@ -116,11 +116,11 @@ c=70
PIHOLE_META_PACKAGE_CONTROL_APT=$( PIHOLE_META_PACKAGE_CONTROL_APT=$(
cat <<EOM cat <<EOM
Package: pihole-meta Package: pihole-meta
Version: 0.4 Version: 0.5
Maintainer: Pi-hole team <adblock@pi-hole.net> Maintainer: Pi-hole team <adblock@pi-hole.net>
Architecture: all Architecture: all
Description: Pi-hole dependency meta package Description: Pi-hole dependency meta package
Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,netcat-openbsd,procps,psmisc,sudo,unzip Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,procps,psmisc,sudo,unzip
Section: contrib/metapackages Section: contrib/metapackages
Priority: optional Priority: optional
EOM EOM
@@ -130,12 +130,12 @@ EOM
PIHOLE_META_PACKAGE_CONTROL_RPM=$( PIHOLE_META_PACKAGE_CONTROL_RPM=$(
cat <<EOM cat <<EOM
Name: pihole-meta Name: pihole-meta
Version: 0.2 Version: 0.3
Release: 1 Release: 1
License: EUPL License: EUPL
BuildArch: noarch BuildArch: noarch
Summary: Pi-hole dependency meta package Summary: Pi-hole dependency meta package
Requires: bash-completion,bind-utils,binutils,ca-certificates,chkconfig,cronie,curl,dialog,findutils,gawk,git,grep,iproute,jq,libcap,lshw,nmap-ncat,procps-ng,psmisc,sudo,unzip Requires: bash-completion,bind-utils,binutils,ca-certificates,chkconfig,cronie,curl,dialog,findutils,gawk,git,grep,iproute,jq,libcap,lshw,procps-ng,psmisc,sudo,unzip
%description %description
Pi-hole dependency meta package Pi-hole dependency meta package
%prep %prep
@@ -143,6 +143,9 @@ Pi-hole dependency meta package
%files %files
%install %install
%changelog %changelog
* Mon Jul 14 2025 Pi-hole Team - 0.3
- Remove nmap-ncat from the list of dependencies
* Wed May 28 2025 Pi-hole Team - 0.2 * Wed May 28 2025 Pi-hole Team - 0.2
- Add gawk to the list of dependencies - Add gawk to the list of dependencies
@@ -164,6 +167,17 @@ for var in "$@"; do
esac esac
done done
if [[ "${runUnattended}" == true ]]; then
# In order to run an unattended setup, a pre-seeded /etc/pihole/pihole.toml must exist
if [[ ! -f "${PI_HOLE_CONFIG_DIR}/pihole.toml" ]]; then
printf " %b Error: \"%s\" not found. Cannot run unattended setup\\n" "${CROSS}" "${PI_HOLE_CONFIG_DIR}/pihole.toml"
exit 1
fi
printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}"
# also disable debconf-apt-progress dialogs
export DEBIAN_FRONTEND="noninteractive"
fi
# If the color table file exists, # If the color table file exists,
if [[ -f "${coltable}" ]]; then if [[ -f "${coltable}" ]]; then
# source it # source it
@@ -1791,8 +1805,12 @@ FTLinstall() {
# Before stopping FTL, we download the macvendor database # Before stopping FTL, we download the macvendor database
curl -sSL "https://ftl.pi-hole.net/macvendor.db" -o "${PI_HOLE_CONFIG_DIR}/macvendor.db" || true curl -sSL "https://ftl.pi-hole.net/macvendor.db" -o "${PI_HOLE_CONFIG_DIR}/macvendor.db" || true
# Stop pihole-FTL service if available
stop_service pihole-FTL >/dev/null # If the binary already exists in /usr/bin, then we need to stop the service
# If the binary does not exist (fresh installs), then we can skip this step.
if [[ -f /usr/bin/pihole-FTL ]]; then
stop_service pihole-FTL >/dev/null
fi
# Install the new version with the correct permissions # Install the new version with the correct permissions
install -T -m 0755 "${binary}" /usr/bin/pihole-FTL install -T -m 0755 "${binary}" /usr/bin/pihole-FTL
@@ -2235,15 +2253,6 @@ main() {
exit 1 exit 1
fi fi
if [[ "${fresh_install}" == false ]]; then
# if it's running unattended,
if [[ "${runUnattended}" == true ]]; then
printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}"
# also disable debconf-apt-progress dialogs
export DEBIAN_FRONTEND="noninteractive"
fi
fi
if [[ "${fresh_install}" == true ]]; then if [[ "${fresh_install}" == true ]]; then
# Display welcome dialogs # Display welcome dialogs
welcomeDialogs welcomeDialogs
+5 -4
View File
@@ -105,9 +105,9 @@ Available commands and options:
Flush the Pi-hole log Flush the Pi-hole log
.br .br
\fB-r, reconfigure\fR \fB-r, repair\fR
.br .br
Reconfigure or Repair Pi-hole subsystems Repair Pi-hole subsystems
.br .br
\fB-t, tail\fR [arg] \fB-t, tail\fR [arg]
@@ -317,9 +317,10 @@ Switching Pi-hole subsystem branches
Switch to core development branch Switch to core development branch
.br .br
\fBpihole arpflush\fR \fBpihole networkflush\fR
.br .br
Flush information stored in Pi-hole's network tables Flush information stored in Pi-hole's network table
Add '--arp' to additionally flush the ARP table
.br .br
\fBpihole api stats/summary\fR \fBpihole api stats/summary\fR
+52 -42
View File
@@ -9,7 +9,7 @@
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" PI_HOLE_SCRIPT_DIR="/opt/pihole"
# PI_HOLE_BIN_DIR is not readonly here because in some functions (checkout), # PI_HOLE_BIN_DIR is not readonly here because in some functions (checkout),
# they might get set again when the installer is sourced. This causes an # they might get set again when the installer is sourced. This causes an
@@ -20,7 +20,7 @@ readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
# shellcheck source=./advanced/Scripts/COL_TABLE # shellcheck source=./advanced/Scripts/COL_TABLE
source "${colfile}" source "${colfile}"
readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source=./advanced/Scripts/utils.sh # shellcheck source=./advanced/Scripts/utils.sh
source "${utilsfile}" source "${utilsfile}"
@@ -96,8 +96,18 @@ flushFunc() {
exit 0 exit 0
} }
# Deprecated function, should be removed in the future
# use networkFlush instead
arpFunc() { arpFunc() {
"${PI_HOLE_SCRIPT_DIR}"/piholeARPTable.sh "$@" shift
echo -e " ${INFO} The 'arpflush' command is deprecated, use 'networkflush' instead"
"${PI_HOLE_SCRIPT_DIR}"/piholeNetworkFlush.sh "$@"
exit 0
}
networkFlush() {
shift
"${PI_HOLE_SCRIPT_DIR}"/piholeNetworkFlush.sh "$@"
exit 0 exit 0
} }
@@ -147,10 +157,11 @@ uninstallFunc() {
versionFunc() { versionFunc() {
exec "${PI_HOLE_SCRIPT_DIR}"/version.sh exec "${PI_HOLE_SCRIPT_DIR}"/version.sh
exit 0
} }
reloadDNS() { reloadDNS() {
local svcOption svc str output status pid icon FTL_PID_FILE local svcOption svc str output status pid icon FTL_PID_FILE sigrtmin
svcOption="${1:-reload}" svcOption="${1:-reload}"
# get the current path to the pihole-FTL.pid # get the current path to the pihole-FTL.pid
@@ -169,7 +180,10 @@ reloadDNS() {
str="FTL is not running" str="FTL is not running"
icon="${INFO}" icon="${INFO}"
else else
svc="kill -RTMIN ${pid}" sigrtmin="$(pihole-FTL sigrtmin 2>/dev/null)"
# Make sure sigrtmin is a number, otherwise fallback to RTMIN
[[ "${sigrtmin}" =~ ^[0-9]+$ ]] || unset sigrtmin
svc="kill -${sigrtmin:-RTMIN} ${pid}"
str="Reloading DNS lists" str="Reloading DNS lists"
icon="${TICK}" icon="${TICK}"
fi fi
@@ -264,6 +278,7 @@ Time:
LogoutAPI LogoutAPI
echo -e "${OVER} ${TICK} ${str}" echo -e "${OVER} ${TICK} ${str}"
exit 0
} }
piholeLogging() { piholeLogging() {
@@ -519,7 +534,8 @@ Options:
reloadlists Update the lists WITHOUT flushing the cache or restarting the DNS server reloadlists Update the lists WITHOUT flushing the cache or restarting the DNS server
checkout Switch Pi-hole subsystems to a different GitHub branch checkout Switch Pi-hole subsystems to a different GitHub branch
Add '-h' for more info on checkout usage Add '-h' for more info on checkout usage
arpflush Flush information stored in Pi-hole's network tables"; networkflush Flush information stored in Pi-hole's network tables
Add '--arp' to additionally flush the ARP table ";
exit 0 exit 0
} }
@@ -528,7 +544,7 @@ if [[ $# = 0 ]]; then
fi fi
# functions that do not require sudo power # functions that do not require sudo power
need_root=1 need_root=
case "${1}" in case "${1}" in
"-h" | "help" | "--help" ) helpFunc;; "-h" | "help" | "--help" ) helpFunc;;
"-v" | "version" ) versionFunc;; "-v" | "version" ) versionFunc;;
@@ -536,31 +552,32 @@ case "${1}" in
"-q" | "query" ) queryFunc "$@";; "-q" | "query" ) queryFunc "$@";;
"status" ) statusFunc "$2";; "status" ) statusFunc "$2";;
"tricorder" ) tricorderFunc;; "tricorder" ) tricorderFunc;;
"allow" | "allowlist" ) listFunc "$@";;
"deny" | "denylist" ) listFunc "$@";;
"--wild" | "wildcard" ) listFunc "$@";;
"--regex" | "regex" ) listFunc "$@";;
"--allow-regex" | "allow-regex" ) listFunc "$@";;
"--allow-wild" | "allow-wild" ) listFunc "$@";;
"enable" ) piholeEnable true "$2";;
"disable" ) piholeEnable false "$2";;
"api" ) shift; apiFunc "$@"; exit 0;;
# we need to add all arguments that require sudo power to not trigger the * argument # we need to add all arguments that require sudo power to not trigger the * argument
"allow" | "allowlist" ) need_root=0;; "-f" | "flush" ) need_root=true;;
"deny" | "denylist" ) need_root=0;; "-up" | "updatePihole" ) need_root=true;;
"--wild" | "wildcard" ) need_root=0;; "-r" | "repair" ) need_root=true;;
"--regex" | "regex" ) need_root=0;; "-l" | "logging" ) need_root=true;;
"--allow-regex" | "allow-regex" ) need_root=0;; "uninstall" ) need_root=true;;
"--allow-wild" | "allow-wild" ) need_root=0;; "-d" | "debug" ) need_root=true;;
"-f" | "flush" ) ;; "-g" | "updateGravity" ) need_root=true;;
"-up" | "updatePihole" ) ;; "reloaddns" ) need_root=true;;
"-r" | "repair" ) ;; "reloadlists" ) need_root=true;;
"-l" | "logging" ) ;; "setpassword" ) need_root=true;;
"uninstall" ) ;; "checkout" ) need_root=true;;
"enable" ) need_root=0;; "updatechecker" ) need_root=true;;
"disable" ) need_root=0;; "arpflush" ) need_root=true;; # Deprecated, use networkflush instead
"-d" | "debug" ) ;; "networkflush" ) need_root=true;;
"-g" | "updateGravity" ) ;; "-t" | "tail" ) need_root=true;;
"reloaddns" ) ;;
"reloadlists" ) ;;
"setpassword" ) ;;
"checkout" ) ;;
"updatechecker" ) ;;
"arpflush" ) ;;
"-t" | "tail" ) ;;
"api" ) need_root=0;;
* ) helpFunc;; * ) helpFunc;;
esac esac
@@ -572,20 +589,15 @@ fi
# Check if the current user is not root and if the command # Check if the current user is not root and if the command
# requires root. If so, exit with an error message. # requires root. If so, exit with an error message.
if [[ $EUID -ne 0 && need_root -eq 1 ]];then # Add an exception for the user "pihole" to allow the webserver running gravity
echo -e " ${CROSS} The Pi-hole command requires root privileges, try:" if [[ ( $EUID -ne 0 && ${USER} != "pihole" ) && -n "${need_root}" ]]; then
echo -e " ${CROSS} This Pi-hole command requires root privileges, try:"
echo -e " ${COL_GREEN}sudo pihole $*${COL_NC}" echo -e " ${COL_GREEN}sudo pihole $*${COL_NC}"
exit 1 exit 1
fi fi
# Handle redirecting to specific functions based on arguments # Handle redirecting to specific functions based on arguments
case "${1}" in case "${1}" in
"allow" | "allowlist" ) listFunc "$@";;
"deny" | "denylist" ) listFunc "$@";;
"--wild" | "wildcard" ) listFunc "$@";;
"--regex" | "regex" ) listFunc "$@";;
"--allow-regex" | "allow-regex" ) listFunc "$@";;
"--allow-wild" | "allow-wild" ) listFunc "$@";;
"-d" | "debug" ) debugFunc "$@";; "-d" | "debug" ) debugFunc "$@";;
"-f" | "flush" ) flushFunc "$@";; "-f" | "flush" ) flushFunc "$@";;
"-up" | "updatePihole" ) updatePiholeFunc "$@";; "-up" | "updatePihole" ) updatePiholeFunc "$@";;
@@ -593,15 +605,13 @@ case "${1}" in
"-g" | "updateGravity" ) updateGravityFunc "$@";; "-g" | "updateGravity" ) updateGravityFunc "$@";;
"-l" | "logging" ) piholeLogging "$@";; "-l" | "logging" ) piholeLogging "$@";;
"uninstall" ) uninstallFunc;; "uninstall" ) uninstallFunc;;
"enable" ) piholeEnable true "$2";;
"disable" ) piholeEnable false "$2";;
"reloaddns" ) reloadDNS "reload";; "reloaddns" ) reloadDNS "reload";;
"reloadlists" ) reloadDNS "reload-lists";; "reloadlists" ) reloadDNS "reload-lists";;
"setpassword" ) SetWebPassword "$@";; "setpassword" ) SetWebPassword "$@";;
"checkout" ) piholeCheckoutFunc "$@";; "checkout" ) piholeCheckoutFunc "$@";;
"updatechecker" ) shift; updateCheckFunc "$@";; "updatechecker" ) shift; updateCheckFunc "$@";;
"arpflush" ) arpFunc "$@";; "arpflush" ) arpFunc "$@";; # Deprecated, use networkflush instead
"networkflush" ) networkFlush "$@";;
"-t" | "tail" ) tailFunc "$2";; "-t" | "tail" ) tailFunc "$2";;
"api" ) shift; apiFunc "$@";;
* ) helpFunc;; * ) helpFunc;;
esac esac
+1 -1
View File
@@ -2,5 +2,5 @@ pyyaml == 6.0.2
pytest == 8.4.1 pytest == 8.4.1
pytest-xdist == 3.8.0 pytest-xdist == 3.8.0
pytest-testinfra == 10.2.2 pytest-testinfra == 10.2.2
tox == 4.27.0 tox == 4.28.4
pytest-clarity == 1.0.1 pytest-clarity == 1.0.1