I have many power shell scripts on my servers that report to me status
I have Exchange 2016 CU10 DAG setup 2 NODES
My scripts all point to NODE 1 but when I take down NODE 1 for maintenance No email is received. thru NODE 2 I changed the script to point to NODE 2 and it works great.
How can I automatically switch from NODE 1 to NODE 2?
Here is a sample script I use.
$Server = hostname
$Subject = “$Server Delete VSS Report”
$Body = “Open attachment for Delete VSS Report”
$From = “no-reply@mynet.com”
$To = “systems-alert@mynet.com”
$LogFolder = “c:\util\logs”
$LogFile = “vss.txt”
remove-item -path $LogFolder$LogFile -Force
vssadmin list shadows >>$LogFolder$LogFile
vssadmin delete shadows /all /quiet >>$LogFolder$LogFile
vssadmin list shadows >>$LogFolder$LogFile
$PSEmailServer = “SERV021-N1.MYNET.COM”
Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -smtpserver $PSEmailServer -attachment “$LogFolder$LogFile”
SERV021-N2.MYNET.COM IS NODE 2
Thank you
Tom
You could detect the availability of the two servers and make a decision which to use for Hostname
$Mailservers = @("HOST1","HOST2")
if (Test-Connection -ComputerName $Mailservers[0] -Count 1 -Quiet) {
# first Server is UP
$Nailserver = $Mailservers[0]
}
elseif (Test-Connection -ComputerName $Mailservers[1] -Count 1 -Quiet) {
# second server is UP
$Mailserver = $Mailservers[1]
} else {
Write-Error "No Mailservers Available"
}
Schlauge,
Thanks for the fast reply.
That’s a good start.
I should have mentioned that both server are up and running. When I meant it was in Maint Mode it is applying upgrades to Exchange.
I need a check that will detect the Exchange Server is in Maint mode.
Thoughts?
How do you determine the state where you would consider the Exchange server in MaintMode? Are you running another script, externally, tp place the Exchange server into Maintenance. That should point you in the right direction.
I’m not an Exchange guy, but I found this with a quick search.
Get-ServerComponentState
or
Exchange Maintenance Mode
Schlauge
the output of the Get-servercomponetstate is
[PS] C:\Windows\system32>get-servercomponentstate -Identity SERV021-N1
Server Component State
SERV021-N1.mynet.com ServerWideOffline Active
SERV021-N1.mynet.com HubTransport Active
SERV021-N1.mynet.com FrontendTransport Active
SERV021-N1.mynet.com Monitoring Active
SERV021-N1.mynet.com RecoveryActionsEnabled Active
SERV021-N1.mynet.com AutoDiscoverProxy Active
SERV021-N1.mynet.com ActiveSyncProxy Active
SERV021-N1.mynet.com EcpProxy Active
SERV021-N1.mynet.com EwsProxy Active
SERV021-N1.mynet.com ImapProxy Active
SERV021-N1.mynet.com OabProxy Active
SERV021-N1.mynet.com OwaProxy Active
SERV021-N1.mynet.com PopProxy Active
SERV021-N1.mynet.com PushNotificationsProxy Active
SERV021-N1.mynet.com RpsProxy Active
SERV021-N1.mynet.com RwsProxy Active
SERV021-N1.mynet.com RpcProxy Active
SERV021-N1.mynet.com UMCallRouter Active
SERV021-N1.mynet.com XropProxy Active
SERV021-N1.mynet.com HttpProxyAvailabilityGroup Active
SERV021-N1.mynet.com ForwardSyncDaemon Inactive
SERV021-N1.mynet.com ProvisioningRps Inactive
SERV021-N1.mynet.com MapiProxy Active
SERV021-N1.mynet.com EdgeTransport Active
SERV021-N1.mynet.com HighAvailability Active
SERV021-N1.mynet.com SharedCache Active
SERV021-N1.mynet.com MailboxDeliveryProxy Active
SERV021-N1.mynet.com RoutingUpdates Active
SERV021-N1.mynet.com RestProxy Active
SERV021-N1.mynet.com DefaultProxy Active
SERV021-N1.mynet.com Lsass Active
SERV021-N1.mynet.com RoutingService Active
SERV021-N1.mynet.com E4EProxy Active
SERV021-N1.mynet.com CafeLAMv2 Active
SERV021-N1.mynet.com LogExportProvider Active
Is there a way to check the HubTransport Status Active vs Inactive?
Also this would need to be run remotely since all servers do not have exchange powershell commands available
They all can remote into the exchange server using New-PSSEssion
Thoughts
Schlauge
How about this command
Test-NetConnection -ComputerName SERV021-N1 -port 25
ComputerName : SERV021-N1
RemoteAddress : 10.2.2.17
RemotePort : 25
InterfaceAlias : Local Area Connection
SourceAddress : 10.2.2.69
TcpTestSucceeded : True
You can try PSRemoting to get the state of the HubTrasnport component.
The overall logic is the same:
<pre class="brush:powershell"
$servers = @("SERV021-N1","SERV021-N2")
Some work to get status of Server
maybe invoke-command or somethignelse
I dont know what this code should be, this needs to get the status of the Hubtransport from each Exchange server
$ExchHubTransportStatus = Invoke-Command -ComputerName $servers -ScriptBlock {get-servercomponentstate -Component HubTransport }
if ( $ExchHubTransportStatus[0].state -eq "Active") {
# first Server is UP
$Mailserver = $ExchHubTransportStatus[0].Server
}
elseif ($ExchHubTransportStatus[0].state -eq "Active") {
# second server is UP
$Mailserver = $ExchHubTransportStatus[1].Server
} else {
Write-Error "No Mailservers Available"
}
Schlauge
Your code below looks good can we use this
Test-NetConnection -ComputerName SERV021-N1 -port 25
Output is in my last posting above
This will test if port 25 is available
$Mailservers = @(“HOST1”,“HOST2”)
if (Test-Connection -ComputerName $Mailservers[0] -Count 1 -Quiet) {
first Server is UP
$Nailserver = $Mailservers[0]
}
elseif (Test-Connection -ComputerName $Mailservers[1] -Count 1 -Quiet) {
second server is UP
$Mailserver = $Mailservers[1]
} else {
Write-Error “No Mailservers Available”
}
TcpTestSucceeded : False when port is not available
I would do like below.
Create a function to send mail, then
$Mailservers = @("HOST1","HOST2")
$Mailserver = ''
$Mailservers | ForEach-Object -Process {
if (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
$Mailserver = $_
}
}
if($Null -ne $Mailserver){
# Call send mail function here
}
else{
# Throw here
}
#Or
$Mailserver = Test-Connection -ComputerName $Mailservers -Count 1 -ErrorAction SilentlyContinue
if($Null -ne $Mailserver){
# Call send mail function here
$ActiveServer = ($Mailserver|Get-Random)
}
else{
# Throw here using $Error
}
btwn,
It would be great if you update the post by formatting the code using code posting tags , this makes other to easily understand your code, below link will help you.
Guys
[PRE]Invoke-Command -ComputerName $Mailservers[0] -FilePath c:\Util\get-exchangestatus.ps1 [/PRE]
I created the script get-exchangestatus.ps1 on my exchange servers in the folder c:\util
but when I run the command above it returns command not found.
So I placed the script on my local c drive in the same folder it ran but had this error
[PRE]Active Directory operation failed on . The supplied credential for ‘MYNET\myaccount’ is invalid.
+ CategoryInfo : NotSpecified: ( , ADInvalidCredentialException
+ FullyQualifiedErrorId : [Server=SERV021-N1,RequestId=2b810f62-fd8c-4b97-91cb-69958d5d7ba0,TimeStamp=9/30/2018 1:44:28 PM] [FailureCategory=Cmdlet-ADInvalidCredentialException] 3A548CBE
+ PSComputerName : SERV021-N1.mynet.com
[/PRE]
So how can I run the script on the exchange server?
I have many servers that need to run this script
I thought the invoke-command would work
Thoughts?
Tom,
Start with Enter-PSSession from a Powershell prompt
[PRE]
Enter-PSSEssion -ComputerName SERV021-N1
[/PRE]
If you can connect to connect to the remote server, then run the Get-ServerComponentState
[PRE]
Get-ServerComponentState -Component HubTransport
[/PRE]
IF this works, then you can expand that to the previous script I provided. It looks like my last, got garbled somehow…
[PRE]
$Mailservers = @(“SERV021-N1”,“SERV021-N2”)
$MailSvrStatus = Invoke-Command -ComputerName $mailServers -ScriptBlock {
Enter-PSSEssion -ComputerName SERV021-N1
if ( {
# first Server is UP
$Nailserver = $Mailservers[0]
}
elseif (Test-Connection -ComputerName $Mailservers[1] -Count 1 -Quiet) {
# second server is UP
$Mailserver = $Mailservers[1]
} else {
Write-Error “No Mailservers Available”
}
[/PRE]
You are passing credentials, please show us the script you are using and note the
“To format code, use the Text…” above the text box for formatting the code.
Backticks or [pre] cannot be used to format code
Tom,
Break this down into little chunks…
…Can you get the Mail Server’s Maint Status from the server running the script…
Try starting with Enter-PSSession from a PowerShell prompt
Enter-PSSEssion -ComputerName SERV021-N1
If you can connect to connect to the remote server, then run the Get-ServerComponentState from within the session
Get-ServerComponentState -Component HubTransport
IF all this works, then you can expand that to the previous script I provided. It looks like my last, got garbled somehow…
$Mailservers = @("SERV021-N1","SERV021-N2")
$mailServerStatus = Invoke-Command -ComputerName $mailServers -ScriptBlock { Get-ServerComponentState -Component HubTransport }
if ( $mailServerStatus[0].State -eq "Active" ) {
# first Server is UP
$Nailserver = $Mailservers[0].Server
}
elseif ($mailServerStatus[1].State -eq "Active") {
# second server is UP
$Mailserver = $Mailservers[1].Server
} else {
Write-Error "No Mailservers Available"
}
if you can’t get a PSSession to get the data you are looking for… then you’ll need some other method to get the state of Maintenance Mode.
I hope this helps…
Get-ServerComponentState -Component HubTransport
The term ‘Get-ServerComponentState’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (Get-ServerComponentState:String) , CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
In the scriptblock can I load the exchange powershell module?
The command is this how do I wrap that in the scriptb block?
Add-PSSnapin microsoft.exchange.management.powershell.SnapIn;
Thank
Perhaps a better way to tell if the Exchange server is ready, is to utilize the Test-ServiceHealth cmdlet. That is provided you are running the script from the Exchange management shell where this cmdlet is available.
It will check if all required services are running on said Exchange server. And if they are running, you will be OK to send mail through it.
Simply edit to your original sample script, replace the following line:
$PSEmailServer = "SERV021-N1.MYNET.COM"
with an if statement that checks if services are running, then sets your PSEmailServer variable with the server name:
if (Test-ServiceHealth -Server SERV021-N1.MYNET.COM | ? {$_.RequiredServicesRunning -eq $False})
{$PSEmailServer = "SERV021-N2.MYNET.COM"}
else {$PSEmailServer = "SERV021-N1.MYNET.COM"}
I Like Cheese
Nice command but I still need the exchange powershell modules loaded.
I am trying this
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$MailServers[0]/PowerShell/ -Authentication Kerberos -Credential $cred
Import-PSSession $Session -DisableNameChecking
$mailServerStatus = Get-ServerComponentState -Identity $EMailservers[0] -Component HubTransport