powerdns / pdnsutil / remove-record
The PowerDNS nameserver pdnsutil utility has an add-record
, but no
remove-record
. How can we remove records programmatically for many
domains at once?
Step one: make sure we can list all domains. For our PowerDNS 4 setup, we could do the following:
$ list_all() {
( for type in master native; do pdnsutil list-all-zones $type; done ) |
grep -vE '^.$|:' | sort -V; }
$ list_all
domain1.tld
domain2.tld
...
Step two: filter the domains where we want to remove anything. In this case, a stale MX record we want removed.
$ list_relevant() {
list_all | while read zone; do pdnsutil list-zone $zone |
grep -q IN.*MX.*oldmx.example.com && echo $zone; done; }
$ list_relevant
domain2.tld
...
Step three: remove the record. Here we’ll resort to a bit of magic using
the EDITOR
environment variable and sed(1)
.
$ EDITOR=cat pdnsutil edit-zone domain2.tld
; Warning - every name in this file is ABSOLUTE!
$ORIGIN .
domain2.tld 86400 IN SOA ns1.example.com info.example.com 2010090200 14400 3600 604800 3600
...
domain2.tld 86400 IN MX 20 oldmx.example.com
...
We can replace that phony cat
“editor” with a sed
command instead:
$ update_record() {
EDITOR="/bin/sed -i -e '/IN.*MX.*oldmx.example.com/d'" pdnsutil edit-zone $1
pdnsutil increase-serial $1; pdns_control notify $1; }
$ yes a | update_record domain2.tld
Checked 8 records of 'domain2.tld', 0 errors, 0 warnings.
Detected the following changes:
-domain2.tld 86400 IN MX 20 backupmx.osso.nl
(a)pply these changes, (e)dit again, (r)etry with original zone, (q)uit:
Adding empty non-terminals for non-DNSSEC zone
SOA serial for zone domain2.tld set to 2010090202
Added to queue
Wrapping it all up:
$ list_relevant | while read zone; do yes a | update_record $zone; done
Note that I ran into bug 4185 concerning edit-zone complaining about TXT records without quotes. I could edit those two records by hand. Fixing all of that is for another day.