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:
- Go into the server room use each machine's local console.
- PROBLEM: It's cold and loud in the server room.
- 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).
- Remote desktop on each server, and make changes there.
- PROBLEM: make even one mistake and you lose contact with the server whose IP you are changing, necessitating a trip to the server room.
- Use your KVM-over-IP to do the job from the comfort of your desk.
- 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.