Setup Alert when SQL Agent Down using Task Scheduler - sql

I am looking something to setup alert notification when SQL agent is down, sometimes when windows patch apply or server get rebooted SQL Agent is not restarting even though we have set up SQL Agent properties Auto Restart SQL Server if it stops unexpectedly
Auto Restart SQL Server Agent if it stops unexpectedly.
I have also tried to setup services on Component service on server to at Recovery tab, First Failure Restart the service and also restarted service rebooted but didn't work.
Is it any way I can get the alert so I can restart service manually when it's Agent is down it it will trigger to restart the job when Agent it's down.

$AgentStatus = (Get-Service -ComputerName <CompName> -Name <SqlServerAgentName> | Where-Object {$_.Status -eq "Stopped"} | Measure-Object).Count
If($AgentStatus -eq 1){
Start-Service -Name SqlServerAgentName
$SMPTPort = <Specify port number>
$From = "email1#domain.com"
$To = "email2#domain.com"
$Subject = "The SQL Server Agent Service in $env:ComputerName has been restarted."
$Body = "The SQL Server Agent Service <SqlServerAgentName> was in a Stopped state and has been restarted."
$SMTPServer = "SMTP SERVER"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, $SMPTPort)
$SMTPClient.EnableSsl = $false
$SMTPClient.Send($From, $To, $Subject, $Body)}

You can try creating a batch file below which checks for service status. This sends an SMTP mail (using powershell) along with restarting service again.
for /F "tokens=3 delims=: " %%H in ('sc query "MyServiceName" ^| findstr " STATE"') do (
if /I "%%H" NEQ "RUNNING" (
powershell -ExecutionPolicy ByPass -Command Send-MailMessage -SmtpServer SMTPSERVER -To someone#domain.com -From noreply#domain.com -Subject Testing -Body Service_Not_Running
net start "MyServiceName"
)
)
Once you have the script ready, create a task scheduler to call the batch file. Run the scheduler every 1 hr or so.

Related

Azure Monitoring Database performance

I need to compile the following information: "a scheduled report that shows the DB environment state. From free space to performance, failed jobs and anything else that can cause a DB not to function correctly."
I keep getting referred to the same learn.microsoft links but for some reason i just get progressively more confused.
Can someone please help me with a step by step instruction on how to achieve the above mentioned?
All our DBs are on Azure VMs.
I tried Chat GPT for the disk sizes and it gave me a Power Shell code. <
# Connect to your Azure account
Connect-AzAccount
# Get a list of all virtual machines in your subscription
$vms = Get-AzVM
# Loop through the list of virtual machines
foreach ($vm in $vms) {
# Get the details of each virtual machine
$vmName = $vm.Name
$vmSize = $vm.HardwareProfile.VmSize
# Get a list of all disks attached to the virtual machine
$disks = Get-AzDisk | Where-Object { $_.ManagedBy -eq $vm.Id }
# Loop through the list of disks
foreach ($disk in $disks) {
# Get the details of each disk
$diskName = $disk.Name
$diskSize = $disk.DiskSizeGB
$diskType = $disk.StorageAccountType
# Print the virtual machine, disk, and disk size information
Write-Output "VM Name: $vmName"
Write-Output "VM Size: $vmSize"
Write-Output "Disk Name: $diskName"
Write-Output "Disk Size: $diskSize GB"
Write-Output "Disk Type: $diskType"
Write-Output ""
}
}
\>
I could not get free space information or Database information this way.
Your script is working but you are retrieving information about the VMs, not about the SQL Server that is stored within the VMs.
You need to login into the SQL Server inside the VM and run the query that you want:
# Load the Azure RM module
Import-Module AzureRM
# Login to Azure
Login-AzureRmAccount
# Get a list of all Azure VMs
$vms = Get-AzureRmVM
# Loop through each VM
foreach ($vm in $vms) {
# Get the VM's IP address
$ipAddress = (Get-AzureRmPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name ($vm.Name + '-ip')).IpAddress
# Connect to SQL Server on the VM
$connectionString = "Server=$ipAddress;Database=master;User ID=<username>;Password=<password>"
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$connection.Open()
# Execute the SELECT ##VERSION query
$command = $connection.CreateCommand()
$command.CommandText = "SELECT ##VERSION"
$reader = $command.ExecuteReader()
# Display the result
while ($reader.Read()) {
Write-Output $reader.GetValue(0)
}
# Close the connection
$connection.Close()
}
Note that you will need to replace <username> and <password> with the actual SQL Server login credentials for each VM.
Replace the "SELECT ##VERSION" with the query that investigates:
DB environment state
free space
performance
failed jobs
anything else...

Azure Backup. Wait Only Until Snapshot Is Taken, Not Until It's Transferred to Vault

I'm writing a PowerShell script for starting MySQL Server process, initiating backups from Azure Recovery Services, then starting MySQL Server process again.
For my purposes Wait-AzRecoveryServicesBackupJob cmdlet is not suitable, as Azure Backup always takes 10 minutes to take a snapshot and takes 3-24 hours to transfer that snapshot to Vault. How can I wait only until snapshot is taken?
You will need to set up your own polling loop, but unfortunately the Get-AzRecoveryServicesBackupJob doesn't have the properties you need. There are two options available to you in Powershell-- the REST API or the CLI.
Once you've gotten the job info, you can find the individual tasks under properties.extendedInfo.tasksList
Implementing this under the CLI would look something like this:
$resourceGroup = "resourceGroup"
$vaultName = "vaultName"
$jobs = az backup job list --resource-group $resourceGroup --vault-name $vaultName --start-date 28-8-2020 | convertfrom-json
$jobName = $jobs[0].name
$jobStatus = az backup job show --name $jobName --resource-group $resourceGroup --vault-name $vaultName
$taskStatus = $jobStatus.properties.extendedInfo.tasksList | Where-Object { $_.taskId -eq "Take Snapshot"}
While ( $taskStatus.status -ne Completed ) {
Write-Host -Object "Waiting for completion..."
Start-Sleep -minutes 1
$jobStatus = az backup job show --name $jobName --resource-group $resourceGroup --vault-name $vaultName
$taskStatus = $jobStatus.properties.extendedInfo.tasksList | Where-Object { $_.taskId -eq "Take Snapshot"}
}
Write-Host -Object "Done!"

Powershell SMO Can't Connect

I'm having an issue connecting to a SQL Server using SMO when using a ServerConnection. For the last few months this has been working, but now failing. Here is a snippet of the script:
$svrname = "Server"
#Establish Server connection
Write-ColorOutput "Establishing SQL Server Connection to $svrName" "White"
$mysvrConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$mysvrConn.ServerInstance=$svrName
$mysvrConn.LoginSecure = $false
$mysvrConn.Login = "Admin"
$mysvrConn.Password = "Password"
$svr = new-object 'Microsoft.SqlServer.Management.SMO.Server' $mysvrConn
However, the following works.
$svrname = "Server"
$svr = new-object ('Microsoft.SQLServer.Management.SMO.Server') $svrname
And the assemblies:
Write-ColorOutput "Loading assemblies" "White"
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SQLServer.Smo") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null
You almost certainly have permission issues with your SQL login. You are either using the wrong password, or the login does not have the proper creds.
Embarrassingly, when I had this issue, it turned out to be that I had entered the login password incorrectly.
I had expected a specific error stating the login failed. Instead it was the more generic: Failed to connect to server localhost., which threw me off.
Like you, I ran a test with the $LoginSecure = $True which worked, telling me that the connection to the server was fine. Only then did I spot my typo and was on my way to SMO bliss.

Using Powershell to create user in RabbitMQ via API

I'm trying to create a powershell script that setups user "George" after installing RabbitMQ on a new machine.
I can't figure out why this script doesn't work.
The last step gives me a 404 {"error":"Object Not Found","reason":"\"Not Found\"\n"}
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'george' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('george', $secpasswd2)
$body = #{
'password' = 'george'
'tags' = 'administrator'
} | ConvertTo-Json
$vhosts1 = ''
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
write '1:' $vhosts1
$vhosts2 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/' -Method get -credential $credAdmin2
write '2:' $vhosts2
$body2 = #{
'username' = 'george'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
write '3:' $body2
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
write '4:' $vhosts3
I've also tried formatting the last step like this:
http://localhost:15672/api/permissions/george
Same 404 error.
I've tried about 20,000 different ways of sending the command in. From matching other examples perfectly to trying some abstract art and voodoo magic. While watching the managment tool for RabbitMQ I can see George is created. And he has an empty vhost. So the first 3 steps work perfectly.
Alright man, you know that I love you, because I'd never heard of RabbitMQ before tonight. In the last hour, I've installed it on my Windows machine, and now have used this awesome guide here to the API and kind of learned about how it works.
So, when I run your same process step by step , I see everything happen as you state:
George gets created:
Since your second step is listing the current permissions of the user running the API call, I next see output of the guest account, which has full perms. Then onto step 3, which builds the target permissions for George.
username : george
write : .*
read : .*
configure : .*
vhost : /
From here, Step 4. When I run this step manually after the previous step...it works! However, if I run this too quickly, if I run the whole script at once, I will get a 404 error. It seems that behind the scenes in RabbitMQ a slight pause is needed for the files to be updated with the new user. When I deleted the user and tried the whole script again too quickly, I got 404's for every step, pretty much.
However, if I add a little Start-Sleep 5 to pause 5 seconds...
The whole process completed. The key place to add a pause is after Step 1 and it seems to need about four or five seconds.
Making it pretty
Now of course, I couldn't stop there, so I decided to add a few more minor pauses to improve output readability and also ensure that each operation completes. I added some purty looking "OK" messages after the step completes, and then added a finishing confirmation of permissions by doing one last API call for the current user.
Here's the completed output
Completed Script
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'stephen' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('stephen', $secpasswd2)
$body = #{
'password' = 'stephen'
'tags' = 'administrator'
} | ConvertTo-Json
Write-host "About to create new user $(($body | ConvertFrom-Json).Password)..." -NoNewline
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
Write-Host '1: Results:' $vhosts1
$body2 = #{
'username' = 'stephen'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
Write-Output "Desired perms for new user $(($body | ConvertFrom-Json).Password)" $body2
Write-host "Setting perms for new user..." -NoNewline
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
Start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
write '4:' $vhosts3
'Retrieiving perms for new user to confirm...'
Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -Method get -credential $credAdmin2
Now I just hope I'll get a chance to use RabbitMQ ever again...
finally stumpled upon a powershell library someone else wrote for interacting with the RabbitMQ api.
https://github.com/mariuszwojcik/RabbitMQTools/blob/master/en-US/about_UnEsapingDotsAndSlashes.help.txt
I found out that certain versions of powershell replace %2f with the / before sending it to rabbit. If you use this guys functions found here:
https://github.com/mariuszwojcik/RabbitMQTools
Everything runs beautifully. Really great library he put together.
I'm late to this question. I love Powershell too, but I used a .bat file to run the native RabbitMQ commands as shown below. I needed to add a user, a vhost, and hook those two up. I wanted a script so any new developer could run it.
cd /D c:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.14\sbin
echo cd completed
call rabbitmqctl add_user bts mypass
call rabbitmqctl set_user_tags bts administrator
call rabbitmqctl add_vhost base
call rabbitmqctl set_permissions -p base bts ".*" ".*" ".*"
Echo ----List Command to confirm results --------
call rabbitmqctl list_vhosts
call rabbitmqctl list_user_permissions bts
I suppose you could call these from Powershell too. I guess downside of this is that you have to be on the machine running RabbitMQ.

Call WCF Service from bat file

is it possible to call a Methode of a WCF Service in a bat file. We want to test if the WCF Service works correct after the Server was restartet.
There are no commands within the BAT file universe that will allow you to contact a WCF service directly, however you could use a BAT file to run an existing console program that can connect and interact with a WCF service. So the answer is both yes and no; not directly, but through a separate program yes.
If you need some simple, clickable way of accessing a WCF service, I'd go with a Powershell or VB script (assuming you're in a windows environment).
Maybe you will be able to use PowerShell? It would be easier then. Create script with content:
$url = 'http://yoursite.url/example.svc'
$action = "`"http://some.namespace/method`""
$SOAPRequest = [xml]#'heregoesxmlmessage'#
write-host "Sending SOAP Request To Server: $url"
$soapWebRequest = [System.Net.WebRequest]::Create($url)
$soapWebRequest.Headers.Add("SOAPAction", $action)
$soapWebRequest.ContentType = "text/xml;charset=`"utf-8`""
$soapWebRequest.Accept = "text/xml"
$soapWebRequest.Method = "POST"
write-host "Initiating Send."
$requestStream = $soapWebRequest.GetRequestStream()
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host "Send Complete, Waiting For Response."
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host "Response Received."
$ReturnXml.OuterXml | out-file ".\test.xml"
write-host $ReturnXml.OuterXml
As mentioned in the other answers Powershell is probably the best way to go using the New-WebServiceProxy cmdlet.
http://technet.microsoft.com/library/hh849841.aspx
Example from the link above:
PS C:\> $URI = "http://www.webservicex.net/uszip.asmx?WSDL"
PS C:\>$zip = New-WebServiceProxy -Uri $URI -Namespace WebServiceProxy -Class USZip
PS C:\> $zip.getinfobyzip(20500).table
CITY : Washington
STATE : DC
ZIP : 20500
AREA_CODE : 202
TIME_ZONE : E