基于嵌套循环中的if语句中断完整脚本



我有一个很长的脚本,在这个脚本中,我正在对从csv文件收集的一些输入进行验证。因此,脚本将首先导入CSV文件,然后读取它们,根据某些条件,它将激发脚本的一部分。脚本的这一部分将执行一些验证,为了正确执行这些验证,我必须在循环中执行一个循环。如果此验证不成功,则脚本将打印一个错误,然后中断。

问题是脚本没有中断。

我知道,如果您已经为外循环标识了一个标签并在Break命令中调用了这个标签,那么Break将只中断当前循环或外循环。

我需要的是,如果这个验证在嵌套循环中不成功,那么整个脚本应该中断,也不要退出,因为我需要让控制台运行。

例如,在下面的中,您将发现针对名为vSphereSXEnvironmentInfo的变量中的值运行的循环。此变量包含从CSV文件中导入的信息。这些信息与NSX、vCenter服务器和主机vCenter服务器的FQDN、用户名和密码有关(请注意,您可以忽略此处的NSX位,我只是专注于vCenter信息(,此CSV文件将保存每个站点的这些信息。

这个变量中包含的信息的例子是:

SiteName                              : CGSM-Site
NsxManagerFqdn                        : CGSM-NSX.nfv.gss
NsxManagerUser                        : admin
NsxManagerPassword                    : VMware1!
vCenterFqdn                           : CGSM-VCSA.nfv.gss
vCenterUser                           : administrator@vsphere.local
vCenterPassword                       : VMware1!
vCenterHostingNsxFqdn                 : CGSM-VCSA.nfv.gss
vCenterHostingNsxUser                 : administrator@vsphere.local
vCenterHostingNsxPassword             : VMware1!
vCenterHostingvCenterFqdn             : CGSM-VCSA.nfv.gss
vCenterHostingvCenterUser             : administrator@vsphere.local
vCenterHostingvCenterPassword         : VMware1!
PrimaryNsxManagerFQDN                 : NotUsed
PrimaryNsxManagerUser                 : NotUsed
PrimaryNsxManagerPassword             : NotUsed
vCenterRegisteredToPrimaryNsxFQDN     : NotUsed
vCenterRegisteredToPrimaryNsxUser     : NotUsed
vCenterRegisteredToPrimaryNsxPassword : NotUsed
NsxController1IP                      : 192.168.4.61
NsxController2IP                      : 192.168.4.62
NsxController3IP                      : 192.168.4.63
NsxControllersPassword                : VMware1!VMware1!
SiteName                              : CGSR-Site
NsxManagerFqdn                        : CGSR-NSX.nfv.gss
NsxManagerUser                        : admin
NsxManagerPassword                    : VMware1!
vCenterFqdn                           : CGSR-VCSA.nfv.gss
vCenterUser                           : administrator@vsphere.local
vCenterPassword                       : VMware1!
vCenterHostingNsxFqdn                 : CGSM-VCSA.nfv.gss
vCenterHostingNsxUser                 : administrator@vsphere.local
vCenterHostingNsxPassword             : VMware1!
vCenterHostingvCenterFqdn             : CGSM-VCSA.nfv.gss
vCenterHostingvCenterUser             : administrator@vsphere.local
vCenterHostingvCenterPassword         : VMware1!
PrimaryNsxManagerFQDN                 : CGSM-NSX.nfv.gss
PrimaryNsxManagerUser                 : admin
PrimaryNsxManagerPassword             : VMware1!
vCenterRegisteredToPrimaryNsxFQDN     : CGSM-VCSA.nfv.gss
vCenterRegisteredToPrimaryNsxUser     : administrator@vsphere.local
vCenterRegisteredToPrimaryNsxPassword : VMware1!
NsxController1IP                      : 192.168.4.61
NsxController2IP                      : 192.168.4.62
NsxController3IP                      : 192.168.4.63
NsxControllersPassword                : VMware1!VMware1!

在下面的脚本中,您将发现如下过程:

1-为变量中的每一组信息运行For循环。

2-第一次验证将检查连接,为此,我正在为创建的PS对象创建另一个for Loop,添加所需的目的地以检查连接。如果连接测试失败,则它将中断

3-第二次验证将检查用户名和密码,为此,我正在为创建的PS对象创建另一个for Loop,添加所需的目的地以检查连接。如果用户名和密码不正确,则它将破坏

4-第三次验证将检查注册情况。

脚本一直在继续。所以当我故意在CSV文件中输入错误的用户名和密码时,代码会达到这个级别,并按预期出错,但它会从内部循环中断,进入外部循环,这也是预期的。

我需要的是打破整个剧本。

代码:

#region ######### - 2nd Sub-Sub-Section - SubSubSectionName: CheckIfNoNsxIsInUse.
###########################################
#######    Start of SubSubSection    ######
###########################################
#SubSection Description:    This SubSubsection will check and validate the info gathered from the vSphere-NSX-Required-Info.csv file with respect to the IP/FQDN connectivity as well as the credentials if the NSX is Not in use.
#--------------------------------------------------------------------------------------------------------
Write-Host -BackgroundColor:Black -ForegroundColor:Gray "           NSX-v is not used, Checking credentials and connection to vCenter Server only."     
Foreach ($Line in $vSphereNSXEnvironmentInfo) {                     
Write-Host -BackgroundColor:Black -ForegroundColor:Gray "           Working on Site " $Line.SiteName " For " $Line.vCenterFqdn "."
#region ££££££££££££ - 1st Sub-Sub-Sub-Section - SubSubSubSectionName: CheckConnectivity.
###########################################
#######    Start of SubSubSection    ######
###########################################
#SubSubSubSection Description:  This SubSubSubsection will check Connectivity.
#-------------------------------------------------------------------------
#Check Connectivity for vCenter Servers in each provided site in the vSphere-NSX-Required-Info.csv

#Test Connection for the endpoint and the hosting endpoint over port 22 and 443.
Write-Host -BackgroundColor:Black -ForegroundColor:Gray "           Checking connection over port 22 and 443."      
#Create an array and add 22 and 443 in it to loop over it to make it easier for the code instead of writing the code twice once for 22 and another for 443
$RequiredPorts = @("22","443")
Foreach ($Port in $RequiredPorts) {
#Create an array with the FQDN of the End point and check of the hosting vCenter is the same and if not then add it to the array.
#Reason of creating this array is to minimize the code by running a loop for this array rather than writing the code 4 times once for each endpoint.
$EndPoints = @()
$EndPoints += $Line.vCenterFqdn
If ($Line.vCenterFqdn -NE $Line.vCenterHostingvCenterFqdn) {$EndPoints += $Line.vCenterHostingvCenterFqdn}                      
Foreach ($Target in $EndPoints) {
$TestConnection = Test-NetConnection -Port $Port -ComputerName $Target
If ($TestConnection.PingSucceeded -Eq "True") {
Write-Host -BackgroundColor:Black -ForegroundColor:DarkYellow "             Connection to "$Target " over port " $Port " is successful."
}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Connection to "$Target " over port " $Port " is not successful."
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Please check connectivity to endpoints and try again."
start-sleep 5
Break
}               
}
}

###########################################
#######   End of SubSubSubSection     #####
########################################### 
#---------------------------------------------- 
#endregion
#-----------------------------------------
#region ££££££££££££ - 2nd Sub-Sub-Sub-Section - SubSubSubSectionName: CheckValidityOfUsername&Password.
###########################################
#######    Start of SubSubSection    ######
###########################################
#SubSubSubSection Description:  This SubSubSubsection will check Validity of Username and Passwords.
#-------------------------------------------------------------------------
#Check validity of usernames and passwords for each NSX/vCneter EndPoint in each provided site in the vSphere-NSX-Required-Info.csv
Write-Host -BackgroundColor:Black -ForegroundColor:Gray "           Checking gathered Username and Passwords for all vCenter Servers."  

#Create an HashTable with the FQDN, Username and Password for each Endpoint and then add the HashTable to an Array Variable to have all Endpoints info.
#Reason of creating this array is to minimize the code by running a loop for this array rather than writing the code once for each endpoint.
#Create the Variable, Note that the Hashtable will be created each time the tool go to another endpoint to delete the priviouse info of the priviouse endpoint.
$EndPointsArray = @()
#1- Add Working vCenter Server to the HashTable
$EndPointsHashTable = @{}
$URL = "https://" + $Line.vCenterFqdn + "/rest/com/vmware/cis/session"
$EndPointsHashTable.add("Description", "vCenter")
$EndPointsHashTable.add("EndPoint", $Line.vCenterFqdn)
$EndPointsHashTable.add("URI", $URL)
$Header = vCenterAuthurization -Username $Line.vCenterUser -Password $Line.vCenterPassword
$EndPointsHashTable.add("Header", $Header)
$EndPointsArray += $EndPointsHashTable
#2- Add vCneter Server VM Hosting vCenter Server to the HashTable if exists.
If ($Line.vCenterFqdn -NE $Line.vCenterHostingvCenterFqdn) {
$URL = "https://" + $Line.vCenterHostingvCenterFqdn + "/rest/com/vmware/cis/session"
$EndPointsHashTable.add("Description", "vCenter")
$EndPointsHashTable.add("EndPoint", $Line.vCenterHostingvCenterFqdn)
$EndPointsHashTable.add("URI", $URL)
$Header = vCenterAuthurization -Username $Line.vCenterHostingvCenterUser -Password $Line.vCenterHostingvCenterPassword
$EndPointsHashTable.add("Header", $Header)
$EndPointsArray += $EndPointsHashTable
}

#Run the llop for the gathered info in the EndPointsArray Array Variable and validate the Username and Password.
Foreach ($EndPoint in $EndPointsArray) {
#Check if it is a Controller and if yes then use the Push-SSH.
If ($EndPoint.Description -Eq "Controller") {
$TestCredentials = New-SSHSession -ComputerName $EndPoint.URI -Credential $EndPoint.Header -AcceptKey
If ($TestCredentials) {Write-Host -BackgroundColor:Black -ForegroundColor:DarkYellow "              Username and Password for " $EndPoint.URI " are successful."}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Provided Username and Password for " $EndPoint.URI " are incorrect."
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Please check Username and Password and try again."
start-sleep 5
Break
}
}
#Run the validation for the rest normally as there will be nothing else that will need to use Push-SSH rathere than Invoke-WebRequest.
$TestCredentials = Invoke-WebRequest -Uri $EndPoint.URI -Method Post -Headers $head
If ($TestCredentials.StatusCode -Eq 200) {Write-Host -BackgroundColor:Black -ForegroundColor:DarkYellow "               Username and Password for " $EndPoint.URI " are successful."}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Provided Username and Password for " $EndPoint.URI " are incorrect."
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Please check Username and Password and try again."
start-sleep 5
Break
}
}

###########################################
#######   End of SubSubSubSection     #####
########################################### 
#---------------------------------------------- 
#endregion
#-----------------------------------------                      
#region ££££££££££££ - 3rd Sub-Sub-Sub-Section - SubSubSubSectionName: CheckHostingvCenterServers.
###########################################
#######    Start of SubSubSection    ######
###########################################
#SubSubSubSection Description:  This SubSubSubsection will Check and validate the hosting vCenterServer.
#-------------------------------------------------------------------------              
#Check if the Hosting vCenter Server are correct.
Write-Host -BackgroundColor:Black -ForegroundColor:Gray "           Validating Hosting vCenter for vCenter VM"  
#Second will check if vCenterHostingvCenterFqdn field is not set to NotUsed which would indicate that there are are a Hosting vCenter.
#If vCenterHostingvCenterFqdn is set to a value other than NotUsed, Connect and try to locate the NSX Manager VM.
#If vCenterHostingvCenterFqdn is set to NotUsed then Connect to the Working vCenter and Locate the NSX Manaver VM.
If ($Line.vCenterHostingvCenterFqdn -NE "NotUsed") {
Write-Host -BackgroundColor:Black -ForegroundColor:Gray "           Another hosting vCenter for vCenter is detected in csv file, confirmting info." 
#At this point there is a hosting vCenter to the NSX, Connect and try to locate.
$HostingvCenterforWorkingvCenterConnection = Connect-VIServer -Server $Line.vCenterHostingvCenterFqdn -User $Line.vCenterHostingvCenterUser -Password $Line.vCenterHostingvCenterPassword -Force -WarningAction SilentlyContinue -InformationAction Ignore -ErrorAction SilentlyContinue
If ($HostingvCenterforWorkingvCenterConnection) {
#Convert Working NSX Manager FQDN to IP to be used in locating the VM.
$vCenterIpConverted = [System.Net.Dns]::GetHostAddresses($Line.vCenterFqdn)
$LocatevCenterVM = Get-VM -Server $HostingvCenterforWorkingvCenterConnection | Where-Object -FilterScript { $_.Guest.Nics.IPAddress -contains "$vCenterIpConverted" } 
Disconnect-VIServer -Server $HostingvCenterforWorkingvCenterConnection -Force -WarningAction SilentlyContinue -InformationAction SilentlyContinue -ErrorAction SilentlyContinue -Confirm:$false
If ($LocatevCenterVM) {
Write-Host -BackgroundColor:Black -ForegroundColor:DarkYellow "             " $Line.vCenterFqdn " is confirmed to be Hosted on " $Line.vCenterHostingvCenterFqdn "."
}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                " $Line.vCenterFqdn " VM could not be found on " $Line.vCenterHostingvCenterFqdn "."
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Data Provided are incorrect, please check and try again."
start-sleep 5
Break
}
}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Unable to connect to " $Line.vCenterHostingvCenterFqdn "."
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Please check and try again."
start-sleep 5
Break
}
}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Gray "           No additional hosting vCenter is detected in csv file, confirmting info."   
#At this point there are no additional hosting vCenter are detected, which means that the NSX is hosted on vCenterFqdn, Connect and try to locate..
$HostingvCenterforWorkingvCenterConnection = Connect-VIServer -Server $Line.vCenterFqdn -User $Line.vCenterUser -Password $Line.vCenterPassword -Force -WarningAction SilentlyContinue -InformationAction Ignore -ErrorAction SilentlyContinue
If ($HostingvCenterforWorkingvCenterConnection) {
#Convert Working NSX Manager FQDN to IP to be used in locating the VM.
$vCenterIpConverted = [System.Net.Dns]::GetHostAddresses($Line.vCenterFqdn)
$LocateNsxVM = Get-VM -Server $HostingvCenterforWorkingvCenterConnection | Where-Object -FilterScript { $_.Guest.Nics.IPAddress -contains "$vCenterIpConverted" } 
Disconnect-VIServer -Server $HostingvCenterforWorkingvCenterConnection -Force -WarningAction SilentlyContinue -InformationAction SilentlyContinue -ErrorAction SilentlyContinue -Confirm:$false
If ($LocateNsxVM) {
Write-Host -BackgroundColor:Black -ForegroundColor:DarkYellow "             " $Line.vCenterFqdn " is confirmed to be Hosted on " $Line.vCenterFqdn "."
}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                " $Line.vCenterFqdn " VM could not be found on " $Line.vCenterFqdn "."
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Data Provided are incorrect, please check and try again."
start-sleep 5
Break
}
}
Else {
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Unable to connect to " $Line.vCenterFqdn "."
Write-Host -BackgroundColor:Black -ForegroundColor:Red "                Please check and try again."
start-sleep 5
Break
}
}
#----------------------------------------------------------------               

###########################################
#######   End of SubSubSubSection     #####
########################################### 
#---------------------------------------------- 
#endregion
#-----------------------------------------

} #End of rht Foreach Loop started at the begining.
Write-Host -BackgroundColor:Black -ForegroundColor:DarkGreen "                  All dtat in vSphere-NSX-Required-Info.csv file was validated."  
###########################################
#######    End of SubSubSection      ######
########################################### 
#---------------------------------------------- 
#endregion

PowerShell中的流控制语句(如foreach循环(支持标签,格式为:labelname,如:

:outer
foreach($Array in @(@(1,2),@(3,4),@(5,6))){
:inner
foreach($Value in $Array){
Write-Host $Value
if($Value -eq 1){
break inner
}
if($Value -eq 4){
break outer
}
}    
}

在上面的示例中,内部循环中的第一个if条件将仅跳过值2,而第二个if条件将跳过所有其他条件,因为break指令应用于outer循环。

注意,:是标签名称的而不是部分,因此break inner打断了:inner前面的循环(感谢mklement0指出它(

最新更新