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

时间:2018-07-24 15:52:41

标签: powershell

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

问题在于脚本没有中断。

我了解,如果您已识别到外部循环的标签并在break命令中调用了该标签,则Break仅会中断当前循环或外部循环。

我需要的是,如果此验证在嵌套循环中失败,那么整个脚本应该会中断并且也不会退出,因为我需要保持控制台运行。

例如,在下面的示例中,您将发现针对名为vSphereNSXEnvironmentInfo的变量中的值运行的循环。此变量保存从CSV文件之一导入的信息。这些信息与NSX,vCenter Server和托管vCenter Server的FQDN,用户名和密码(PS,您可以在这里忽略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- Second Validation将检查用户名和密码,为此,我将为创建的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

1 个答案:

答案 0 :(得分:4)

PowerShell中的

流控制语句(如foreach循环)支持{em>标签,格式为: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条件将跳过其他所有内容,因为{{1} }指令适用于break循环。

请注意,outer不是标签名称的一部分,因此:中断了以break inner开头的循环(由于mklement0 for pointing it out