The answer is DNS scavenging which would be the butter on that slice of bread just to make it taste better and proper. But we want to make sure that the butter we put on the bread is not rotten. Otherwise we would need to throw the bread to the bin with the butter... ok, enough of this nonsense.
DNS scavenging essentially deletes stale / old records from the given DNS Zone. What we want to make sure that the scavenging process is properly configured otherwise we could end up losing very valuable DNS records and cause outages - believe me, you don't want an outage caused by something as fundamental as DNS.
There are a couple of rules we need to keep in mind:
- The scavenging intervals have to be thought through - I'd go with the default settings 7+7 days
- There should be only 1 DNS server scavenging the zone regularly even if we have lots of e.g. Domain Controllers hosting the zone.
- The zone should be restricted and only that one server should be allowed to scavenge the zone. You can read more about scavenging e.g. here and here
Create an object where you will store the name of the DNS host, the scavenging interval set on that server and the default aging state on that server:
$sObject = "" | select hostname,ScavengingInterval,LastScav,DefaultAgingState
Take the output of dnscmd /info and go through each line:
dnscmd $srv /info | %{
If it's the line where scavenging info is stored, do some regex matching to take out the bits you need:
if($_ -imatch "last scav"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
Add it to your output object:
$sObject.LastScav = $value
It will show you an output like this:
Note the date and result of the last scavenging run |
The full script:
# get the list of Windows DNS servers from the pipe
$hostlist = @($Input)
$hostlistlength = ($hostlist | measure).count
# go through each host
foreach($srv in $hostlist){
$sObject = "" | select hostname,ScavengingInterval,LastScav,DefaultAgingState
# run dnscmd to get the detailed info of each DNS server
dnscmd $srv /info | %{
$value = $null
# pick out the data from dnscmd output with regex matches
if($_ -imatch "last scav"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
$sObject.LastScav = $value
$value = $null
}
elseif($_ -imatch "ScavengingInterval"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
$sObject.ScavengingInterval = $value
$value = $null
}
elseif($_ -imatch "DefaultAgingState"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
$sObject.ScavengingInterval = $value
$value = $null
}
}
$sObject
}
Thanks for posting this script. It helped me discover that no server was doing the scavenging. I did change is slightly. I changed the read from the text file to read from AD to list all domain controllers and pipe that to into the hostlist. I kept the file reader in there so now if I want some DNS servers, I build the list. Otherwise I check them all.
ReplyDelete$hostlist = [system.directoryservices.activedirectory.domain]::GetCurrentDomain() | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name}
# $hostlist = Get-Content $scriptFile
$hostlistlength = ($hostlist | measure).count
I resolved my missing Hostname with this code:
ReplyDelete# get the list of Windows DNS servers from the pipe
$hostlist = @($Input)
$hostlist = [system.directoryservices.activedirectory.domain]::GetCurrentDomain() | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name}
# $hostlist = Get-Content $scriptFile
$hostlistlength = ($hostlist | measure).count
# go through each host
foreach($srv in $hostlist){
$sObject = "" | select hostname,ScavengingInterval,LastScav,DefaultAgingState
# run dnscmd to get the detailed info of each DNS server
dnscmd $srv /info | %{
$value = $null
# pick out the data from dnscmd output with regex matches
if($_ -imatch "server name"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
$sObject.hostname = $value
$value = $null
}
elseif($_ -imatch "last scav"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
$sObject.LastScav = $value
$value = $null
}
elseif($_ -imatch "ScavengingInterval"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
$sObject.ScavengingInterval = $value
$value = $null
}
elseif($_ -imatch "DefaultAgingState"){
$value = ([regex]::Match($_, "= .+$")).value -replace "= ",""
$sObject.DefaultAgingState = $value
$value = $null
}
}
$sObject
}