Home / HomePage / Scripts / Remotely change IPs en masse

Remotely change IPs en masse


I once needed to reassign static IP addresses for a whole bunch of Windows servers. Now there are at least 3 ways one can manually go about this, and problems involved in each:

  1. Go into the server room use each machine's local console. 
    1. PROBLEM: It's cold and loud in the server room. 
    2. PROBLEM: no easy way to ping-test each server from some other server. (switching back and forth between consoles will be tedious and error-prone).
  2. Remote desktop on each server, and make changes there.
    1. PROBLEM: make even one mistake and you lose contact with the server whose IP you are changing, necessitating a trip to the server room.
  3. Use your KVM-over-IP to do the job from the comfort of your desk.
    1. PROBLEM: you don't have KVM-over-IP
And the main problem with all three of these is that it's a boring, repetitious task - the easiest kind of tasks for humans to make mistakes with. But it's also critical that it be gotten exactly right, for the obvious reason that if the IP is configured incorrectly, the server cannot be reached. Boring and repetitious (but critical) tasks are the very best ones to automate. In the best case scenario, your automation gets everything right, which is good. But even in the worst case scenario, your automation makes the same mistake, the same way, every time. Which makes mistakes easier to correct (as opposed to human-made mistakes, which tend to be imaginatively unique).

So I wrote this batchfile to automate the task of changing IP addresses for a lot of Windows servers. Today a friend of mine remembered I had discussed it, and asked if I could give him a copy. I decided it would be better to give the whole internet a copy!

@echo off
::script to change IP on a bunch of servers using a comma delimited file "servers.txt"
setlocal
for /f "tokens=1-5 delims=," %%a in (servers.txt) do call :setserverIP %%a %%b %%c %%d %%e
goto :eof
echo Done.
endlocal

:pingit
set replycount=0
for /f %%a in ('ping -n 4 %2 ^|findstr /c:"Reply from %2"') do call :incrementcounter
if %replycount% gtr 0 (call :pingsuccess) else call :pingfail
goto :eof

:incrementcounter
set /a replycount= %replycount% + 1
goto :eof

:pingsuccess
echo %1 Successful ping (IP: %2) >>mylog.txt
goto :eof

:pingfail
echo %1 Failed ping (IP: %2) >>mylog.txt
goto :eof

:setserverIP
::note if the line in servers.txt begins with a pound and a space, ignore that line
if {%1}=={#} goto :eof
::write a batchfile with the netsh and registerdns commands
echo netsh interface ip set address name="Local Area Connection" static %2 %3 %4 %5 %6 >%1.cmd
echo ipconfig /registerdns >>%1.cmd
::remotely run the batchfile (copying it there first)
psexec \\%1 -u %1\administrator -p mypassword -c -f %1.cmd
::locally flush dns
ipconfig /flushdns
::sleep ten seconds
echo ...sleeping ten seconds ...
ping -w 1000 -n 10 0.0.0.0 >nul
::ping changed server by new IP
call :pingit %1 %2
goto :eof
 
Reading carefully you can see that the script requires a file called "servers.txt". That file looks like this:
 

# servername,ipaddress,netmask,gateway,gateway metric
test1,10.0.0.222,255.255.255.0,10.0.0.1,1
test2,10.0.0.223,255.255.255.0,10.0.0.1,1
# add as many more lines as you need
# lines that start with a single pound char AND A SPACE will be ignored

 
Now, why did I did I do it this way?
 
I could have used WMIC (something like WMIC /node:servername /user:username path Win32_NetworkAdapterConfiguration where (name like "Local Area Connection") call enablestatic "10.0.0.223", "255.255.255.0"), but WMIC never quite seems to return from a remote session where the IP address has changed. That's a common problem for all remote methods of changing IP address: the second your IP change takes place, the remote session you are using will hang.
 
So this script first builds a new script which will actually make the change.  The new script contains a NETSH command to actually change the ip, and an IPCONFIG /REGISTERDNS to make sure DNS is made aware of the change. Then, using psexec, the locally running script pushes the new script to the server that's being reconfigured, and executes that script locally on the server.
 
Psexec will time out anywhere from 5-30 seconds after the IP changes, and the local batch then continues to run. The local batch flushes DNS caches, then tries to ping the new server - I have it pinging by IP, but a ping by name should also work in most cases. The local batch logs the result of this ping to mylog.txt, then iterates the next line of servers.txt, doing all this again, until all the servers have been touched.
 
This script could probably use a little more errorchecking and/or logging. For instance, what if the initial psexec session never connects? I don't have any handling of that. But the script worked fine for my purposes, and one rule of scripting is - write as good as it needs to be, but not a lot better. For the job I was doing at the time, it was enough to have the log of ping results.

    Post a comment

    Your Name or E-mail ID (mandatory)

     



     RSS of this page