These scripts work correctly but for security reasons I could not use this work. Indeed, we must log before with an user then su in root. Moreover, with these previous scripts, that was not possible to transfert any other files like binaries files. So I decided to work on this problem to avoid to manually update 150 esx.
Sure, some trick exist like "expect" (not included in esx) or cpan perl expect, but it was simpliest to me to improve my scripts.
To use my scripts, just create a file yourfile.zip containing a script yourfile.sh and all needed files
process of these scripts:
script use a computer listing file (here servers.txt file) including all your computers you need to update
Script upload on your esx or linux computers yourfile.zip to /tmp directory, then decompress yourfile.zip and run yourfile.sh file
In update_esx_v2.zip, I give you a script example which permit you to update ESX with 2 patchs
[EDIT 15 february 2012] I re-upload zip file and add some informations in this post
In update.zip, file update.sh script contains all commands to do update
#!/bin/sh # Update cd ESX350-201012404-BG/ esxupdate --nosig update cd .. cd ESX350-201012410-BG/ esxupdate --nosig update cd ..In update.zip, there is also all necessary files used by update.sh
update\ update\update.sh update\ESX350-201012404-BG\ update\ESX350-201012404-BG\contents.xml update\ESX350-201012404-BG\contents.xml.sig update\ESX350-201012404-BG\descriptor.xml update\ESX350-201012404-BG\VMware-esx-scripts-3.5.0-317866.i386.rpm update\ESX350-201012404-BG\headers\ update\ESX350-201012404-BG\headers\contents.xml update\ESX350-201012404-BG\headers\contents.xml.sig update\ESX350-201012404-BG\headers\header.info update\ESX350-201012404-BG\headers\VMware-esx-scripts-0-3.5.0-317866.i386.hdr update\ESX350-201012410-BG\ update\ESX350-201012410-BG\contents.xml update\ESX350-201012410-BG\contents.xml.sig update\ESX350-201012410-BG\descriptor.xml update\ESX350-201012410-BG\vmware-keying-data-1-20100930.noarch.rpm update\ESX350-201012410-BG\headers\ update\ESX350-201012410-BG\headers\contents.xml update\ESX350-201012410-BG\headers\contents.xml.sig update\ESX350-201012410-BG\headers\header.info update\ESX350-201012410-BG\headers\vmware-keying-data-0-1-20100930.noarch.hdr
Now, you can run "run_update.cmd" which run your updates with user esxadmin
(only if this user can do all that you want - if user to connect your esx is not esxadmin change line with set usern=esxadmin)
@echo off set usern=esxadmin set zipfile=update.zip set computerfile=servers.txt if "%1"=="" goto :nopass set password=%1 cscript //nologo update_esx.vbs %computerfile% %zipfile% %usern% %password% goto :eof :nopass echo you need a password for user %usern% goto :eof
To run your update with user esxadmin then su root
@echo off set usern=esxadmin set userroot=root set zipfile=update.zip set computerfile=servers.txt if "%1"=="" goto :nopass if "%2"=="" goto :nopass2 set password=%1 set pwdroot=%2 cscript //nologo update_esx.vbs %computerfile% %zipfile% %usern% %password% %userroot% %pwdroot% goto :eof :nopass echo you need a password for user %usern% goto :eof :nopass2 echo you need a password for user %userroot% goto :eof
all computers to update are in file servers.txt below
computer1 computer2 computer3
Main script update_esx.vbs that permit to transfert and decompress "yourfile.zip" and execute "yourfile.sh" on your linux or esx
' ' update_esx.vbs ' ' by F.RICHARD ' ' v1.00 2007 Nov - Initial release ' v1.01 2008 Jan - Display Standard output ' v2.00 2011 Nov - Modify script to use and send ZIP file ' Option Explicit Const ForReading = 1 Const ForWriting = 2 ' ' Detect WScript or CScript ' If InStr(LCase(WScript.FullName), "wscript")>0 Then ' ex: FullName = C:\WINNT\system32\wscript.exe WScript.Echo "This script must be run under CScript." WScript.Quit End If ' ' Get Command Line Args ' Dim Args Set Args = Wscript.Arguments If Args.Count < 4 Then Wscript.Echo "Syntax : " & WScript.ScriptName & " input_computer_list_file zip_file_to_send_uncompress_and_execute user password" Wscript.Echo "Syntax : " & WScript.ScriptName & " input_computer_list_file zip_file_to_send_uncompress_and_execute user password [root] [root password]" Wscript.Echo " Example : cscript " & WScript.ScriptName & " servers.txt myfile.zip user password" Wscript.Echo " Example : cscript " & WScript.ScriptName & " servers.txt myfile.zip user password root rootpass" Wscript.Echo "" Wscript.Echo "computer_list_file: line begin by # or ; indicate start of a comment, everything after is ignored" Wscript.Echo "" Wscript.Quit End If ' Args(0) = computer list Dim strInputList strInputList = Trim(args(0)) ' Args(1) = zip file to send and execute Dim strScriptToExecute, strCompressFile, strDirectory, strCompressFileExt strCompressFile = Trim(args(1)) strCompressFileExt = Right(strCompressFile, Len(strCompressFile)-InStr(1, strCompressFile, ".") ) If (StrComp(strCompressFileExt, "zip", vbTextCompare) <> 0) Then WScript.Echo "File to send: '" & strCompressFile & "'is not a .zip file" WScript.Quit End If strDirectory = Left(strCompressFile, InStr(1, strCompressFile, ".")-1) strScriptToExecute = strDirectory & ".sh" ' Args(2) = user Dim strUser strUser = Trim(args(2)) ' Args(3) = password Dim strPassword strPassword = Trim(args(3)) ' Args(4) = root name ' Args(5) = root password Dim strRootPassword, strRootName If Args.Count > 5 Then strRootName = Trim(args(4)) strRootPassword = Trim(args(5)) End If ' ' Get Path ' Dim strScriptFullName, strScriptPath strScriptFullName = WScript.ScriptFullName ' ex: C:\Program Files\MyFolder\MyProg.exe strScriptPath = Left(strScriptFullName, InStrRev(strScriptFullName, "\") - 1) ' ex: C:\Program Files\MyFolder Dim objFso Set objFso = CreateObject("Scripting.FileSystemObject") ' ' Test If all Files Exist ' If Not isFileExist(strInputList) Then strInputList = strScriptPath & "\" & strInputList If Not isFileExist(strInputList) Then WScript.Echo "Computer list:" & strInputList & " File Not Exist !" WScript.Quit End If End If WScript.Echo "Computer list:" & strInputList & " File Exist" If Not isFileExist(strCompressFile) Then strCompressFile = strScriptPath & "\" & strCompressFile If Not isFileExist(strCompressFile) Then WScript.Echo "Compress file:" & strCompressFile & """" & " File Not Exist !" WScript.Quit End If End If WScript.Echo "Script to uncompress:" & strCompressFile & " File Exist" Dim strPlink strPlink= strScriptPath & "\" & "plink.exe" If Not isFileExist(strPlink) Then WScript.Echo "PuTTY Link:" & strPlink & " File Not Exist !" WScript.Quit End If WScript.Echo "PuTTY Link:" & strPlink & " File Exist" Dim strPscp strPscp= strScriptPath & "\" & "pscp.exe" If Not isFileExist(strPscp) Then WScript.Echo "PuTTY Secure Copy client:" & strPscp & " File Not Exist !" WScript.Quit End If WScript.Echo "PuTTY Secure Copy client:" & strPscp & " File Exist" Dim objShell, ComSpec Set objShell = CreateObject( "WScript.Shell" ) ComSpec=objShell.ExpandEnvironmentStrings("%ComSpec%") ' ' Read computer list file into dictionary ' Dim objDictionary, return return = ReadFileToDict(strInputList, objDictionary) If return = 0 Then WScript.Echo "Error during computer list file read" WScript.Quit End If ' ' Generate .sh file to execute ' Dim strContent, strScriptToDecFile strScriptToDecFile = "decfile.sh" strContent = "#!/bin/sh" & vbLf & _ "# Unzip " & strCompressFile & " then enter in " & strDirectory & " directory and execute " & strScriptToExecute & " file" & vbLf & _ "cd /tmp" & vbLf & _ "unzip -o " & strCompressFile & vbLf return = WriteStrToFile(strScriptToDecFile, strContent) ' Display file Dim objItem, strServer, objCmd, strCmdline, continue, strGenerateKey For Each objItem in objDictionary strServer = objDictionary.Item(objItem) Wscript.Echo "" WScript.Echo "Server:" & strServer ' Test Connection strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " " & strUser & "@" & strServer & " pwd " strGenerateKey = ComSpec & " /c echo y | """ & strPlink & """ " & strServer & " -pw " & strPassword & " " & strUser WScript.Echo "Test Connection on server " & strServer return = DoConnection(strCmdline, strGenerateKey, strServer, True) If (return > 0) Then strGenerateKey="" Do WScript.Echo "Re-verify Connection on server " & strServer return = DoConnection(strCmdline, strGenerateKey, strServer, True) Loop While (return > 0 and return < 255) If (return > 0) Then WScript.Echo "Transfer " & strScriptToDecFile & " script on server " & strServer strCmdline = ComSpec & " /c """ & strPscp & """ -batch -C -pw " & strPassword & " " & strScriptToDecFile & " " & strUser & "@" & strServer & ":/tmp" return = DoConnection(strCmdline, strGenerateKey, strServer, True) WScript.Echo "Transfer " & strCompressFile & " script on server " & strServer strCmdline = ComSpec & " /c """ & strPscp & """ -batch -C -pw " & strPassword & " " & strCompressFile & " " & strUser & "@" & strServer & ":/tmp" return = DoConnection(strCmdline, strGenerateKey, strServer, True) WScript.Echo "Execute " & strScriptToDecFile & " script on server " & strServer strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " " & strUser & "@" & strServer & " " & "cd /tmp; sh " & strScriptToDecFile return = DoConnection(strCmdline, strGenerateKey, strServer, True) ' if root / or not root If Args.Count > 5 Then objShell.Run "putty.exe -ssh " & strUser & "@" & strServer WScript.Sleep 5000 objShell.AppActivate strServer & " - PuTTY" WScript.Sleep 5000 objShell.SendKeys "" & strPassword & "{ENTER}" WScript.Sleep 5000 objShell.SendKeys "su - " & strRootName & "{ENTER}" WScript.Sleep 5000 objShell.SendKeys "" & strRootPassword & "{ENTER}" WScript.Sleep 5000 objShell.SendKeys "cd /tmp/" & strDirectory & "; sh " & strScriptToExecute & "{ENTER}" WScript.Sleep 5000 Else WScript.Echo "Execute " & strScriptToExecute & " script on server " & strServer strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " " & strUser & "@" & strServer & " " & "cd /tmp/" & strDirectory & "; sh " & strScriptToExecute return = DoConnection(strCmdline, strGenerateKey, strServer, True) End If End If End If Next ' ' Quit ' WScript.Sleep 1000 WScript.Quit '-------------------- ' DoConnection ' ' ' Function DoConnection(strCmdline, strGenerateKey, strServer, displayLogfile) Dim objCmd, return, Continue 'WScript.Echo "cmdline->" & strCmdline Set objCmd = objShell.Exec(strCmdline) Do While objCmd.Status = 0 return = objCmd.stdErr.ReadAll WScript.Sleep 100 Loop If (displayLogfile) Then Dim strStdOut strStdOut = objCmd.StdOut.ReadAll() If (len(strStdOut) > 0) Then Wscript.Echo strStdOut End If End If continue = 0 If Instr(return, "Access denied" ) > 0 Then ' Access denied WScript.Echo "ERROR on server " & strServer & vbCrLf & return continue = 0 Elseif Instr(return, "Unable to open connection" ) > 0 Then ' Unable to open connection WScript.Echo "ERROR on server " & strServer & vbCrLf & return continue = 0 Elseif Instr(return, "ERROR" ) > 0 Then ' FATAL ERROR: Network error: Connection timed out WScript.Echo "ERROR on server " & strServer & vbCrLf & return continue = 0 Elseif Instr(return, "fingerprint" ) > 0 Then If (len(strGenerateKey) > 2) Then WScript.Echo "GENERATE key fingerprint on server " & strServer 'WScript.Echo "generatekey->" & strGenerateKey objShell.Exec(strGenerateKey) continue = 1 Else WScript.Echo "NOT GENERATE key fingerprint " & strServer continue = 2 End If Else continue = 255 'WScript.Echo "Logged on " & strServer & " - " & return End if DoConnection = continue End Function '-------------------- ' isFileExist ' ' Test if File Exist ' Function IsFileExist(strInputFile) Dim objFSO Set objFSO = CreateObject("Scripting.FileSystemObject") If Not objFSO.FileExists(strInputFile) Then Wscript.echo strInputFile & " file not exist !" IsFileExist = False Else IsFileExist = True End If End Function '-------------------- ' ReadFileToDict ' ' Read each line -> put in Dictionary ' strInputfile = file to read ' objDictionary = dictionary for results ' Function ReadFileToDict(strInputFile, ByRef objDictionary) Dim objFSO, objTextFile, strNextLine, i Set objDictionary = CreateObject("Scripting.Dictionary") Set objFSO = CreateObject("Scripting.FileSystemObject") If isFileExist(strInputFile) Then Set objTextFile = objFSO.OpenTextFile(strInputFile, ForReading) i = 0 Do Until objTextFile.AtEndOfStream strNextLine = Trim(objTextFile.Readline) If ( (Not Left(strNextLine, 1) = "#") _ and (Not Left(strNextLine, 1) = ";") _ and (Len(strNextLine)>1) _ ) Then objDictionary.Add i, strNextLine i = i + 1 End If Loop objTextFile.Close ReadFileToDict = True Else ReadFileToDict = False End If End Function '-------------------- ' WriteStrToFile ' ' Write string to file ' strOutputFile = file to write ' strContent = string to write ' Function WriteStrToFile(strOutputFile, ByRef strContent) Dim objFSO, objTextFile Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.CreateTextFile(strOutputFile, True) ' delete file objTextFile.Write(strContent) objTextFile.Close End Function '--------------------