Files
mailsystem/update_postfwd_defaults.sh
T
chrisandClaude Opus 5.5 95c8ebbe0e postfwd defaults: keep lines with the wanted value, no reload if unchanged
- Never comment out a line that already has the wanted value, even if a
  differing setting of the same variable precedes it.
- update_postfwd_defaults.sh: leave postfwd alone if nothing changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 11:10:49 +01:00

182 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Update /etc/default/postfwd (idempotent) and restart postfwd if needed.
#
# For every variable below:
# - already set to the wanted value -> nothing to do
# - set to a different value -> comment out the current setting
# and add the new one directly below
# - not set at all -> append the new setting
#
# Quotes around values are ignored when comparing (PORT="10040" == PORT=10040).
#
# At the end:
# - file changed -> 'systemctl restart postfwd'
# (ARGS, INET and PORT are start parameters of the
# daemon - a reload does NOT apply them)
# - file unchanged -> postfwd is left alone (no restart, no reload)
#
postfwd_default_file="/etc/default/postfwd"
# - Wanted settings: "VAR|VALUE" (VALUE written exactly as it should appear)
wanted_settings=(
'STARTUP|1'
'CONF|/etc/postfix/postfwd.cf'
'INET|127.0.0.1'
'PORT|10040'
'ARGS|"--summary=600 --cache=0"'
)
# -------------
# --- Some functions
# -------------
log_file="$(mktemp)"
clean_up() {
rm -f "$log_file"
exit $1
}
echononl() {
echo -e -n "$*"
}
echo_ok() {
echo -e "\033[60G[ \033[32mok\033[m ]"
}
echo_skipped() {
echo -e "\033[60G[ \033[33m\033[1mskipped\033[m ]"
}
echo_failed() {
echo -e "\033[60G[ \033[1;31mfailed\033[m ]"
}
error() {
echo ""
echo -e "\t[ \033[31m\033[1mError\033[m ]: $*"
echo ""
}
fatal() {
error "$*"
echo -e "\t\033[31m\033[1mScript will be interrupted\033[m"
echo ""
clean_up 1
}
# - set_postfwd_default <VAR> <VALUE>
# -
# - returns 0 if the file was changed, 1 if nothing changed, 2 on error
# -
set_postfwd_default() {
local _var="$1"
local _val="$2"
local _tmp_file
local _rval
echononl " ${_var}=${_val}"
_tmp_file="$(mktemp)"
awk -v var="$_var" -v val="$_val" '
function unq(s) {
gsub(/^[ \t\r]+|[ \t\r]+$/, "", s)
if (s ~ /^".*"$/ || s ~ /^\047.*\047$/) s = substr(s, 2, length(s) - 2)
return s
}
function is_set(s) { return s ~ ("^[ \t]*" var "=") }
function is_wanted(s) {
sub("^[ \t]*" var "=", "", s)
return unq(s) == unq(val)
}
# - Read the whole file first: a line with the wanted value must stay
# - untouched, no matter which other settings of VAR precede it.
{
line[NR] = $0
if (is_set($0) && is_wanted($0)) found = 1
}
END {
for (i = 1; i <= NR; i++) {
if (! is_set(line[i])) { print line[i] ; continue }
if (is_wanted(line[i])) { print line[i] ; continue }
print "#" line[i]
if (! found) { print var "=" val ; found = 1 }
}
if (! found) print var "=" val
}
' "$postfwd_default_file" > "$_tmp_file" 2> "$log_file"
if [[ $? -ne 0 ]] ; then
echo_failed
error "$(cat "$log_file")"
_rval=2
elif cmp -s "$_tmp_file" "$postfwd_default_file" ; then
echo_skipped
_rval=1
else
# - cat instead of mv/cp keeps owner and permissions of the original file
if cat "$_tmp_file" > "$postfwd_default_file" 2> "$log_file" ; then
echo_ok
_rval=0
else
echo_failed
error "$(cat "$log_file")"
_rval=2
fi
fi
rm -f "$_tmp_file"
return $_rval
}
# -------------
# --- Main
# -------------
[[ "$(id -u)" -eq 0 ]] || fatal "This script must be run as root."
command -v postfwd > /dev/null 2>&1 || fatal "postfwd is not installed."
if [[ ! -f "$postfwd_default_file" ]] ; then
touch "$postfwd_default_file" 2> "$log_file" || fatal "$(cat "$log_file")"
fi
echo ""
echo "Update ${postfwd_default_file}"
echo ""
file_changed=false
errors=false
for _setting in "${wanted_settings[@]}" ; do
set_postfwd_default "${_setting%%|*}" "${_setting#*|}"
case $? in
0) file_changed=true ;;
2) errors=true ;;
esac
done
echo ""
if $errors ; then
fatal "Errors while updating '${postfwd_default_file}' - postfwd NOT restarted."
fi
if ! $file_changed ; then
echo " Nothing changed - postfwd is left alone."
echo ""
clean_up 0
fi
echononl " Restart postfwd (start parameters changed)"
if systemctl restart postfwd > "$log_file" 2>&1 ; then
echo_ok
else
echo_failed
error "$(cat "$log_file")"
clean_up 1
fi
echo ""
clean_up 0