@echo off setlocal enabledelayedexpansion REM ************************************************************************************************ REM * File: get-versions.bat REM * Purpose: Build a csv file of versions of all NetBackup clients, and servers. REM * REM * Vers Date Who Description REM * ---- ---- --- ----------- REM * v0.01 6-AUG-2009 sdo Original version. REM * v0.02 20-SEP-2010 sdo Updates for v6.5.6. REM * v0.03 4-APR-2011 sdo Updates for v7.0.1. REM * v0.04 24-APR-2015 sdo Added more error checking. REM * v0.05 25-APR-2015 sdo Retrieve binaries path, and build command paths. REM ************************************************************************************************ REM * Disclaimer REM * ---------- REM * This script was developed and tested using: REM * - Windows 2008 R2 SP1 REM * - NetBackup Server v7.6.0.4 REM * REM * This script is not endorsed, nor has it been tested, by Symantec. Neither the author, nor REM * Symantec, shall accept any liability from any harm, loss, or damage caused by the use REM * and/or mis-use of this script, either in its original form, or in a modified form. Use of REM * this script in its original, or modified, form is entirely at the end user's own risk. REM * This script is furnished on an example basis only, and may not be suitable for any given REM * environment. REM ************************************************************************************************ REM * Sharing REM * ------- REM * This script is free to share and modify, as long as this entire header section is kept with REM * the script, and maintained and updated appropriately as any changes are made. REM ************************************************************************************************ REM * Notes REM * ----- REM * 1) This script will create a sub-folder named '\data', within which it retains any previous REM * results from bpgetconfig. This is useful in that it speeds up re-runs of this script. REM * 2) However, the above does mean that, after sometime, it may be prudent to manually delete REM * the sub-folder, so that the script will re-fetch client details - and it is probably REM * especially important to delete the '\data' sub-folder after doing a round of client REM * upgrades and/or patches. REM * 3) This script can appear to be slow to run if you have lots of clients that do not resolve REM * in DNS and/or do not ping. Search for the string "_MOD_ME_" in this script for two REM * places where if you de-REM (i.e. uncomment) then the script may run quicker. REM * 4) Another thing that can be done, is to create a static lookup file of "owner" names, i.e. REM * a list of client names and some kind of descriptive text, which will then be included REM * in the "owner" column of the CSV file created by this script. REM * e.g. create a plain text (use Notepad) file named "get-versions.own", and enter: REM * clienta TeamA REM * client-B team B REm * ...i.e. a list of client names, one space character, and then any text including any... REM * ...spaces, but do not use round brackets ( ) in the text, as this confuses DOS/batch. REM ************************************************************************************************ set z_script_started=!date! !time:~0,8! set z_path=%~dp0 set z_name=%~n0 set z_debug=NO REM ************************************************************************************************ REM ************************************************************************************************ REM *** To make re-runs of this script faster, we collect/save the the client queries... set z_data=!z_path!data if not exist "!z_data!" mkdir "!z_data!" REM ************************************************************************************************ REM ************************************************************************************************ REM *** Build some file names for use by this script... REM *** REM *** The 'dat' files are actually saved in the "\data" sub-folder. The variable 'z_file_dat' is REM *** actually re-defined later. It is only listed here to remind us that we do make use of REM *** another file later in the script. set z_file_csv=!z_path!!z_name!.csv set z_file_cli=!z_path!!z_name!.cli set z_file_dat=!z_path!!z_name!.dat set z_file_own=!z_path!!z_name!.own set z_file_ser=!z_path!!z_name!.ser set z_file_log=!z_path!!z_name!.log set z_file_tmp=!z_path!!z_name!.tmp set z_file_txt=!z_path!!z_name!.txt if exist "!z_file_csv!" del "!z_file_csv!" if exist "!z_file_cli!" del "!z_file_cli!" if exist "!z_file_dat!" del "!z_file_dat!" if exist "!z_file_log!" del "!z_file_log!" if exist "!z_file_ser!" del "!z_file_ser!" if exist "!z_file_tmp!" del "!z_file_tmp!" if exist "!z_file_txt!" del "!z_file_txt!" REM ************************************************************************************************ REM ************************************************************************************************ call :log "" call :log "" call :log "Script started: !z_script_started!" call :log "...hostname: !computername!" call :log "...username: !username!" REM ************************************************************************************************ REM ************************************************************************************************ call :log "" call :log "Checking for presence of NetBackup..." reg query HKLM\Software\Veritas\NetBackup\CurrentVersion\Config /v "client_name" >"!z_file_tmp!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...NetBackup does not appear to be installed on this server, script aborting..." goto :end ) for /f "tokens=1,2,3 skip=1" %%a in ('type "!z_file_tmp!"') do ( set z_client_name=%%c ) reg query HKLM\Software\Veritas\NetBackup\CurrentVersion /v "InstallDir" >"!z_file_tmp!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...cannot locate `InstallDir` registry value, script aborting..." goto :end ) for /f "tokens=1,2,* skip=1" %%a in ('type "!z_file_tmp!"') do ( set z_install_dir=%%c ) reg query HKLM\Software\Veritas\NetBackup\CurrentVersion /v "Install Type" >"!z_file_tmp!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...cannot locate `Install Type` registry value, script aborting..." goto :end ) for /f "tokens=1,2,3,* skip=1" %%a in ('type "!z_file_tmp!"') do ( set z_install_type=%%d ) if /i not "!z_install_type!"=="NetBackup Master Server" ( if /i not "!z_install_type!"=="NetBackup Media Server" ( if /i not "!z_install_type!"=="NetBackup Administration Console" ( call :log "...this script cannot be run on NetBackup installation of `!z_install_type!`, script aborting..." goto :end ) ) ) set z_netbackup_bin=!z_install_dir!NetBackup\bin if not exist "!z_netbackup_bin!" ( call :log "...unable to locate NetBackup binaries folder `!z_netbackup_bin!`, script aborting..." goto :end ) set z_volmgr_bin=!z_install_dir!Volmgr\bin if not exist "!z_volmgr_bin!" ( call :log "...unable to locate Volume Manager binaries folder `!z_volmgr_bin!`, script aborting..." goto :end ) set z_bpclntcmd=!z_netbackup_bin!\bpclntcmd.exe set z_bpgetconfig=!z_netbackup_bin!\admincmd\bpgetconfig.exe set z_bpplclients=!z_netbackup_bin!\admincmd\bpplclients.exe if not exist "!z_bpclntcmd!" ( call :log "...unable to find bpclntcmd at `!z_bpclntcmd!`, script aborting..." goto :end ) if not exist "!z_bpgetconfig!" ( call :log "...unable to find bpgetconfig at `!z_bpgetconfig!`, script aborting..." goto :end ) if not exist "!z_bpplclients!" ( call :log "...unable to find bpplclients at `!z_bpplclients!`, script aborting..." goto :end ) call :log "...NetBackup client name: !z_client_name!" call :log "...NetBackup type: !z_install_type!" call :log "...NetBackup path: !z_install_dir!" call :log "...done..." REM ************************************************************************************************ REM ************************************************************************************************ call :log "" call :log "Determining master server name..." "!z_bpclntcmd!" -pn >"!z_file_tmp!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...call to bpclntcmd failed, status `!z_sts!`, script aborting..." goto :end ) for /f "tokens=1,2,3,4,5" %%a in ('type "!z_file_tmp!"') do ( if /i "%%a %%b %%c %%d"=="expecting response from server" ( set z_master=%%e ) ) call :log "...master server is: !z_master!" call :log "...done..." REM ************************************************************************************************ REM ************************************************************************************************ REM *** Fetch list of clients, and a list of servers of the master... if not exist "!z_file_cli!" ( call :log "" call :log "Listing clients..." "!z_bpplclients!" -allunique -noheader -l > "!z_file_cli!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...call to bpplclients failed, status `!z_sts!`..." goto :end ) call :log "...done..." ) if not exist "!z_file_ser!" ( call :log "" call :log "Listing servers..." "!z_bpgetconfig!" -M !z_master! SERVER > "!z_file_ser!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...call to bpgetconfig for master `!z_master!` failed, status `!z_sts!`..." goto :end ) call :log "...done..." ) REM ************************************************************************************************ REM ************************************************************************************************ REM *** Write a header to the report file. We use a leading underscore, so that when the file is REM *** sorted later, the header floats to the top... (echo "_client",ping,ip,owner,hw,os,patch,type,platform,protocol,product,version_name,version_number,install_path,client_os)>>"!z_file_txt!" REM goto :skip1 REM ************************************************************************************************ REM ************************************************************************************************ Call :log "" call :log "Counting clients and servers..." set /a z_cli_total=0 set /a z_cli_attempted=0 set /a z_cli_suceeded=0 set /a z_cnt=0 for /f "tokens=1,2,3,4" %%a in ('type "!z_file_cli!"') do ( set /a z_cnt+=1 set z_hw=%%c set z_wanted=y if /i "!z_hw!"=="VMware" set z_wanted=n if /i "!z_hw!"=="vmx-07" set z_wanted=n if /i "!z_hw!"=="NDMP" set z_wanted=n if /i "!z_wanted!"=="y" (set /a z_cli_total+=1) ) for /f "tokens=1,2,3" %%a in ('type "!z_file_ser!"') do ( set z_client=%%c find /i """!z_client!""" "!z_file_txt!" >NUL 2>&1 if "!errorlevel!"=="1" ( set /a z_cnt+=1 set /a z_cli_total+=1 ) ) call :log "...found `!z_cli_total!` to check from a total of `!z_cnt!` client/server names..." call :log "...done..." REM ************************************************************************************************ REM ************************************************************************************************ call :log "" call :log "Processing list of clients..." set z_section=clients for /f "tokens=1,2,3,4" %%a in ('type "!z_file_cli!"') do ( set z_client=%%b set z_hw=%%c set z_os=%%d set z_check=yes if /i "!z_hw!"=="VMware" set z_check=no if /i "!z_hw!"=="vmx-07" set z_check=no if /i "!z_hw!"=="NDMP" set z_check=no if /i "!z_check!"=="yes" call :r_check REM if !z_cli_attempted! geq 5 goto :skip1 ) call :log "...done..." :skip1 REM ************************************************************************************************ REM ************************************************************************************************ call :log "" call :log "Processing list of servers..." set z_section=servers for /f "tokens=1,2,3" %%a in ('type "!z_file_ser!"') do ( set z_client=%%c set z_hw= set z_os= find /i """!z_client!""" "!z_file_txt!" >NUL 2>&1 if "!errorlevel!"=="1" call :r_check ) call :log "...done..." :skip2 REM ************************************************************************************************ REM ************************************************************************************************ call :log "" call :log "Sorting output..." sort "!z_file_txt!" /o "!z_file_csv!" call :log "...done..." REM ************************************************************************************************ REM ************************************************************************************************ call :log "" call :log "Totals: call :log "...clients total: !z_cli_total!" call :log "...clients attempted: !z_cli_attempted!" call :log "...clients succeeded: !z_cli_suceeded!" call :log "...output file is: !z_file_csv!" call :log "...done..." if exist "!z_file_tmp!" del "!z_file_tmp!" if exist "!z_file_txt!" del "!z_file_txt!" REM ************************************************************************************************ REM ************************************************************************************************ :end set z_script_finished=!date! !time:~0,8! call :log "" call :log "Script started: !z_script_started!" call :log "Script completed: !z_script_finished!" echo+ pause exit /b REM ************************************************************************************************ REM ************************************************************************************************ REM *** Here we gather the client details... :r_check set /a z_cli_attempted+=1 set z_ping= set z_ip= set z_file_owner= REM set z_hw= Leave this REM'd. REM set z_os= Leave this REM'd. set z_type= set z_platform= set z_protocol= set z_product= set z_version_name= set z_version_number= set z_install_path= set z_client_os= set z_patch_level= call :r_owner call :r_ip REM *** _MOD_ME_ REM *** Comment out this next line, if you want the script to ignore cases where this script is... REM *** ...unable to determine the IP of a client... REM if /i "!z_ip!"=="missing" goto :r_check_skip call :r_alive if /i "!z_ping!"=="no" ( call :log "Client: !z_client! does not ping..." REM *** _MOD_ME_ REM *** Comment out this next line, if you want the script to ignore cases where a client does not ping... REM goto :r_check_skip ) call :log "Checking !z_cli_attempted! of !z_cli_total!, client `!z_client!`..." set z_file_dat=!z_data!\!z_client!.dat if not exist "!z_file_dat!" ( bpgetconfig -g !z_client! -A -L > "!z_file_dat!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...call to bpgetconfig for client `!z_client!` failed, status `!z_sts!`..." goto :eof ) ) for /f "tokens=1,2 delims==" %%a in ('type "!z_file_dat!"') do ( if /i "%%a"=="Client/Master " set z_type=%%b if /i "%%a"=="NetBackup Client Platform " set z_platform=%%b if /i "%%a"=="NetBackup Client Protocol Level " set z_protocol=%%b if /i "%%a"=="Product " set z_product=%%b if /i "%%a"=="Version Name " set z_version_name=%%b if /i "%%a"=="Version Number " set z_version_number=%%b if /i "%%a"=="NetBackup Installation Path " set z_install_path=%%b if /i "%%a"=="Client OS/Release " set z_client_os=%%b if /i "%%a"=="Patch Level " set z_patch_level=%%b ) if not "!z_type!"=="" set z_type=!z_type:~1,99! if not "!z_platform!"=="" set z_platform=!z_platform:~1,99! if not "!z_protocol!"=="" set z_protocol=!z_protocol:~1,99! if not "!z_product!"=="" set z_product=!z_product:~1,99! if not "!z_version_name!"=="" set z_version_name=!z_version_name:~1,99! if not "!z_version_number!"=="" set z_version_number=!z_version_number:~1,99! if not "!z_install_path!"=="" set z_install_path=!z_install_path:~1,99! if not "!z_client_os!"=="" set z_client_os=!z_client_os:~1,99! if not "!z_patch_level!"=="" set z_patch_level=!z_patch_level:~1,99! if "!z_client_os:~-1!"==" " set z_client_os=!z_client_os:~0,-1! set /a z_cli_suceeded+=1 :r_check_skip (echo "!z_client!","!z_ping!","!z_ip!","!z_owner!","!z_hw!","!z_os!","!z_patch_level!","!z_type!","!z_platform!","!z_protocol!","!z_product!","!z_version_name!","!z_version_number!","!z_install_path!","!z_client_os!")>>"!z_file_txt!" goto :eof REM ************************************************************************************************ REM ************************************************************************************************ REM *** Lookup the client name in an optional static list of client owners... :r_owner set z_owner= if not exist "!z_file_own!" goto :eof for /f "tokens=1,* skip=2" %%a in ('find /i "!z_client!" "!z_file_own!"') do ( set z_owner=%%b ) goto :eof REM ************************************************************************************************ REM ************************************************************************************************ REM *** Determine IP, and also detect if client accidentally has a round-robin IP in DNS... :r_ip set z_1st_ip= set z_2nd_ip= nslookup !z_client! >"!z_file_tmp!" 2>&1 for /f "tokens=1,2 skip=4" %%a in ('type "!z_file_tmp!"') do ( if /i "%%a"=="Address:" set z_1st_ip=%%b ) nslookup !z_client! >"!z_file_tmp!" 2>&1 for /f "tokens=1,2 skip=4" %%a in ('type "!z_file_tmp!"') do ( if /i "%%a"=="Address:" set z_2nd_ip=%%b ) if "!z_1st_ip!"=="!z_2nd_ip!" ( set z_ip=!z_1st_ip! if "!z_ip!"=="" set z_ip=missing ) else ( set z_ip=duplicated ) if /i not "!z_ip!"=="missing" goto :eof ping !z_client! -n 1 -w 100 >"!z_file_tmp!" 2>&1 for /f "tokens=1,2,3,4 delims=[] " %%a in ('type "!z_file_tmp!"') do ( if /i "%%a %%d"=="Pinging with" ( set z_ip=%%c ) ) goto :eof REM ************************************************************************************************ REM ************************************************************************************************ REM *** Detect whether client pings or not... :r_alive set z_ping=no ping !z_client! -n 1 -w 100 >"!z_file_tmp!" 2>&1 set z_sts=!errorlevel! if not !z_sts!==0 goto :eof for /f "tokens=1" %%a in ('type "!z_file_tmp!"') do ( if /i "%%a"=="reply" ( set z_ping=yes goto :eof ) if /i "%%a"=="request" goto :eof if /i "%%a"=="unknown" goto :eof ) goto :eof REM ************************************************************************************************ REM ************************************************************************************************ :log (echo !date! !time:~0,8! %~1) (echo !date! !time:~0,8! %~1)>>"!z_file_log!" goto :eof