-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnsaxfr
More file actions
executable file
·352 lines (318 loc) · 9.42 KB
/
nsaxfr
File metadata and controls
executable file
·352 lines (318 loc) · 9.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
#!/bin/sh
#-
# Copyright (c) 2006-2012 Parker Lee Ranney TTEE
# Copyright (c) 2017-2025 Devin Teske <dteske@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
############################################################ IDENT(1)
#
# $Title: Distributed bind9 client for applying nsadmin changes $
# $Id: nsaxfr,v 1.3 2012/05/10 01:15:04 root Exp root $
# $Copyright: 2017-2025 Devin Teske. All rights reserved. $
# $FrauBSD: nsadmin/nsaxfr 2025-09-26 02:05:41 -0700 freebsdfrau $
#
############################################################ INFORMATION
#
# nsaxfr -- Update Bind's installation on secondary NS server. See
# nsadmin on the master server for details.
#
# --------------------------------------------------------------------
# Notes:
# - Requires /etc/nsaxfr.conf to operate
# - Requires user `cm' and appropriate `.ssh/authorized_keys2' file
# - User `cm' needs `sudo /usr/local/bin/nsaxfr' without password
# --------------------------------------------------------------------
# Version History:
# Sep 2025: Release 3.0.3
# - Fix remaining f_filter_errors calls missed in 3.0.2
# - Add missing 'next' to EXIT: line processing in awk script
# - Complete migration to f_suppress_errors implementation
# Sep 2025: Release 3.0.2
# - PERFORMANCE: Replace f_filter_errors with f_suppress_errors
# - Eliminate overhead from error suppression (O(n) -> O(1))
# - Use single awk process instead of multiple grep calls
# - Add streaming error suppression with immediate fflush()
# - Dramatic performance improvement for error-heavy operations
# - Zero overhead when suppress_errors is empty (common case)
# - Whitespace fixes
# Sep 2025: Release 3.0.1
# - Replace hard-coded error filter with configurable suppression
# - Add suppress_errors variable to nsaxfr.conf for customization
# - Default: no error suppression (empty suppress_errors var)
# - Example:
# suppress_errors="Operation not permitted|Permission denied"
# - Add f_filter_errors() function for centralized error handling
# - Maintain backward compatibility while allowing customization
# Sep 2025: Release 3.0
# - PERFORMANCE: Optimize backup from O(N^2) to O(N) complexity
# - Replace sed subprocess calls with shell parameter expansion
# - POSIX-compliant find piping to eliminate subshell overhead
# - Silently filter "Operation not permitted" errors
# Nov 2020: Release 2.5.2
# - Make service reload arguments configurable in nsaxfr.conf
# Nov 2020: Release 2.5.1
# - Fix default views in nsaxfr.conf
# Nov 2020: Release 2.5
# - Miscellaneous fixes
# Nov 2020: Release 2.4
# - Make service name configurable in nsaxfr.conf
# Oct 2019: Release 2.3
# - Rename AXFR software and use modern terminology
# Oct 2019: Release 2.2.2
# - Look for config in proper directory based on OS
# Oct 2019: Release 2.2.1
# - Add -v flag to get version
# - Add usage statement (-h)
# - Comments and other minor edits
# Oct 2019: Release 2.2
# - Runtime OS glue
# Jul 2019: Release 2.1
# - Initial public release.
# Jul 2018: Release 2.0
# - Major rewrite and code cleanup.
# Jun 2017: Release 1.1
# - Ported to FreeBSD.
# Jul 2006: Release 1.0
# - Update files locally on the secondary.
#
############################################################ INCLUDES
NSAXFR_CONF=nsaxfr.conf # See OS Glue
############################################################ GLOBALS
VERSION='$Version: 3.0.3 $'
pgm="${0##*/}" # Program basename
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
#
# Global exit status
#
SUCCESS=0
FAILURE=1
#
# OS Glue
#
: ${SYSTEMD:=}
: ${UNAME_s:=$( uname -s )}
############################################################ FUNCTIONS
have(){ type "$@" > /dev/null 2>&1; }
# usage
#
# Print usage statement to stderr and exit with error status.
#
usage()
{
local optfmt="\t%-5s %s\n"
exec >&2
printf "Usage: %s [-hv]\n" "$pgm"
printf "Options:\n"
printf "$optfmt" "-h" "Print usage and exit."
printf "$optfmt" "-v" "Print version and exit."
exit $FAILURE
}
# msg text ...
#
# Provide a supplied message to the user and the log file.
#
msg()
{
logger -p user.info -t Info "$*"
awk 'sub(/^\\/,"")||1' <<-EOF
\ $*
EOF
}
# sigquit
#
# Process a set of commands when a signal is caught by trap.
#
sigquit()
{
cd "$tmp"
rm -rf *
}
# f_suppress_errors [-c] [command args...]
#
# High-performance batch error suppression using single awk process.
#
# Usage:
# f_suppress_errors < input_file # Filter stdin
# f_suppress_errors -c command args... # Execute command with filtering
#
# The -c mode executes the command, captures both stdout/stderr, applies
# error suppression, and preserves the original command's exit code.
#
exec 9<<'EOF'
BEGIN { exit_status = 0 }
/^EXIT:[0-9]+$/ { exit_status = substr($0, 6); next }
{ # Check if line matches any suppression pattern
if ($0 ~ suppress_errors) { # Suppress this line (don't print)
next
} else { # Print line and immediately flush for responsiveness
print
fflush()
}
}
END { exit exit_status }
EOF
f_suppress_errors_awk=$( cat <&9 )
f_suppress_errors()
{
if [ "$1" = "-c" ]; then
shift 1 # -c
if [ ! "$suppress_errors" ]; then
"$@"
return
fi
{ "$@" 2>&1; echo EXIT:$?; } |
awk -v suppress_errors="$suppress_errors" \
"$f_suppress_errors_awk"
elif [ ! "$suppress_errors" ]; then
cat
else
awk -v suppress_errors="$suppress_errors" \
"$f_suppress_errors_awk"
fi
}
############################################################ MAIN
#
# Process command-line options
#
while getopts "hv?" flag; do
case "$flag" in
v) VERSION="${VERSION#*: }"
echo "${VERSION% $}"
exit $SUCCESS ;;
*) usage # NOTREACHED
esac
done
shift $(( $OPTIND - 1 ))
#
# OS Glue
#
have systemctl && SYSTEMD=1
case "$UNAME_s" in
*BSD*) NSAXFR_CONF="/usr/local/etc/$NSAXFR_CONF" ;;
*) NSAXFR_CONF="/etc/$NSAXFR_CONF"
esac
#
# Load config
#
. "$NSAXFR_CONF" || exit
#
# Setup
#
umask 0022
trap "sigquit; exit" EXIT SIGHUP SIGINT SIGQUIT SIGTERM
mkdir -p "$tmp"
cd "$tmp" || exit
#
# Unpack
#
msg "Unpacking zone tarball: $( date )"
tar xvzf zone.tgz 2>&1 | while read line; do
echo " $line"
done
rm -f zone.tgz
#
# Permissions
#
msg "Changing ownership and permissions: $( date )"
chown -R "$owner:$group" $views
chmod -R g-w $views
#
# Backup
#
msg "Backing up zone files: $( date )"
for view in $views; do
# Use find with newline processing - POSIX compliant
find "$view" -type f | while IFS= read -r file; do
# Use parameter expansion instead of sed for speed
dir="${file%/*}"
base="${file##*/}"
res="$dir/.bak-$base"
[ -e "$nameddir/$file" ] &&
cp "$nameddir/$file" "$nameddir/$res"
done
done
#
# Push
#
msg "Moving files to $nameddir: $( date )"
for view in $views; do
find "$view" -type d -exec mkdir -p "$nameddir/{}" \;
f_suppress_errors -c \
find "$view" -type f -exec mv {} "$nameddir/{}" \;
done
#
# Reload
#
msg "Restarting named: $( date )"
: "${named_service_reload_args:=reload}"
printf "\t\t"
if [ "$SYSTEMD" ]; then
systemctl $named_service_reload_args $named_service
else
service $named_service $named_service_reload_args || pkill -1 named
fi
echo
sleep 1
if ! pgrep named > /dev/null; then
msg "ERROR: named is not running after reload: $( date )"
msg "ERROR: attempting manual restart: $( date )"
if [ "$SYSTEMD" ]; then
systemctl start $named_service
else
service $named_service start
fi
if pgrep named > /dev/null; then
msg "Manual restart succeeded: $( date )"
exit $SUCCESS
fi
msg "ERROR: manual restart failed: $( date )"
msg "ERROR: attempting to roll-back: $( date )"
cd "$nameddir"
for view in $views; do
find "$view" -name ".bak-*" | while IFS= read -r file; do
# Use parameter expansion instead of sed for speed
res="${file/.bak-/}"
f_suppress_errors -c mv "$file" "$res"
done
done
cd - > /dev/null
if [ "$SYSTEMD" ]; then
systemctl start $named_service
else
service $named_service start
fi
if pgrep named > /dev/null; then
msg "Roll-back succeeded: $( date )"
update=0
exit $FAILURE
fi
echo "$USER: $( date )" |
mail -s "nsadmin: roll-back failed" "$critical"
msg "FATAL: roll-back failed ... giving up"
exit $FAILURE
fi
exit $SUCCESS
################################################################################
# END
################################################################################