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.

powerdns nameserver