Print Timestamp of Stop and Start Services into .txt file - powershell

I want timestamp when services is stopped/restarted then output to file. The file will become as attached and send to support.
I cannot output to file as my below query seems got error.
$hostname = $env:computername
$smtpServer = 'smtpServer'
$from = "from"
$recipients = 'recipients'
$Subject = "Services Restarted Successfully on $hostname $ipv4"
$body = "This mail confirms that the service on $hostname $ipv4 is now running."
$ipv4 = (Test-Connection -ComputerName $env:computername -count 1).ipv4address.IPAddressToString
$natip = Invoke-WebRequest ifconfig.me
$timestamp = (Get-Date)
$output = D:\Testing\Restart.txt
$attachment = $output
$service = 'Apache'
Stop service
Stop-Service -name $service -Verbose
do {
Start-sleep -s 5 | Write-Output "$timestamp Services is stopped" | Out-file $output
}
until ((get-service $service).Status -eq 'Stopped')
Start service
start-Service -name $service -Verbose
do {
Start-sleep -s 5 | Write-Output "$timestamp Services is restarted" | Out-file $output
}
until ((get-service $service).Status -eq 'Running')
Send confirmation that service has restarted successfully
Start-Sleep -s 5
Send-MailMessage -To $recipients -Subject $Subject -Body $body ((gsv Apache) | out-string) -From $from -SmtpServer $smtpServer -Attachments $attachment

As stated in above comments, change your code to
Stop-Service -name $service -Verbose
do {
Start-sleep -s 5
Write-Output "$timestamp Services is stopped" | Out-file $output
} until ((get-service $service).Status -eq 'Stopped')
Actually your Start-Sleep cmledt calls output is sent to the pipeline ( Start-sleep - s 5 |...). My guess is that Start-sleep doesn't returns anything, so nothing is send to the pipeline. Based on that Write-Output is not called.
Antoher guess: Assignment to $output fails since your path is not a string, Powershell may interpret the assignment in command mode. Change it to:
$output = "D:\Testing\Restart.txt"

Related

Export Eventlogs and send email

I have written a script to export specific Eventvwr logs based on Source and the script is working as expected, but i am trying to cut short the message form the Eventvwr, i dont to print entire message on the mail.
I am attaching the output of my code below
#
# This script exports consolidated and filtered event logs to CSV
#
#Application error and critical eventlogs for specific EventID:
#Email Details
$FromAddress = 'abc.com'
$ToAddress = '123.com'
$SmtpServer = 'xyz.com'
Set-Variable -Name EventAgeDays -Value 4 #we will take events for the latest 7 days
Set-Variable -Name CompArr -Value #("abcedf.com") # replace it with your server names
Set-Variable -Name LogNames -Value #("Application") # Checking app and system logs
Set-Variable -Name EventTypes -Value #("Information") # Loading only Errors and Warnings
Set-Variable -Name ExportFolder -Value "C:\xxx\"
Set-Variable -Name Source -Value #("123", "111")
$el_c = #() #consolidated error log
$now=get-date
$startdate=$now.adddays(-$EventAgeDays)
$ExportFile=$ExportFolder + "Out" + $now.ToString("yyyy-MM-dd---hh-mm-ss") + ".csv" # we cannot use standard delimiteds like ":"
foreach($comp in $CompArr)
{
foreach($log in $LogNames)
{
foreach ($src in $Source)
{
Write-Host Processing $comp\$log
$el = get-eventlog -ComputerName $comp -log $log -After $startdate -EntryType $EventTypes -Source $src -Newest 1 -InstanceId 30000
$el_c += $el #consolidating
#}
#}
$el_sorted = $el_c | Sort-Object TimeGenerated #sort by time
Write-Host Exporting to $ExportFile
}
}
}
$out = $el_sorted|Select MachineName, EntryType, TimeGenerated, Source, EventID, Message #| Export-CSV $ExportFile -NoTypeInfo #EXPORT
Write-Host Done!
$msgBody = $out
Send-MailMessage -from $FromAddress -to $ToAddress -SmtpServer $SmtpServer -Subject "TL Stage Ingester Status from $CompArr $startdate" -Body ( $msgBody | Out-String)

Powershell get process script not working correctly

I want this script to show me WinWord processes which are running currently and to send an email alert out. Currently the 1st script works if there are WinWord processes running and lists them in an email BUT if they are no WinWord processes running the script fails advising parameter is empty or null, cannot find process.
The second script works if there are no processes and doesn’t throw the null or empty parameter if there are no WinWord processes running but only shows true or false by email. Not the list of processes running. Also would like to add some write host in the script for the email output to say. Below are the number of WinWord’s Processes running.
I am a newbie to PowerShell. I am learning as I go. I also used -erroraction silentlycontinue for the first script but when outputting to email it still fails with empty or null parameter.
Below are the scripts.
Doesn't work if process is not running, cannot accept argument which is null or empty. If process is running works perfect.
$winwords = (get-process -ComputerName Dummyserver -Name Winword |where-object { $_.Count -gt 0})| Out-String
Send-MailMessage -To "Dummyemail.co.uk" -From " Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummy.priv" -Body $winwords
Works if argument is null or empty but an email alert is out which says false or true BUT doesn't display the amount of processes running like the first script.
$processname = "Winword"
$instanceisrunning = (get-process -ComputerName Dummyserver| where-object { $_.Name -eq $processname }).count -gt 0 | Out-String
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body $isrunning
You have the right idea using where-object to limit the processes to just the name you want. The logic you are using for count greater than zero will return a boolean ($true or $false), which is why you are seeing that output.
If you want to always send a message when this is run, you can do this:
$instances = (get-process -ComputerName Dummyserver | where-object { $_.Name -eq $processname })
if($instances.count -gt 0)
{
$message = $instances | Out-String
}
else
{
$message = "No instances running"
}
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body $message
If you only want a message sent when instances are running:
$instances = (get-process -ComputerName Dummyserver | where-object { $_.Name -eq $processname })
if($instances.count -gt 0)
{
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body ($instances | Out-String)
}
Edit: Adding code to work of multiple computers with one email
$computers = #("dummyserver","otherserver","nextserver")
$processName = "WinWord"
$message = "$processName is running on the following:"
foreach ($computer in $computers)
{
$message += "Hostname: $computer"
$instances = (Get-Process -ComputerName $computers | Where-Object { $_.Name -eq $processName })
if($instances.count -gt 0)
{
$message += ($instances | Out-String)
}
else
{
$message += "No instances running"
}
}
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body $message
you can use ErrorAction as silentlyContinue which will make your script run even if there is an error "NO Winword instances".
$winwords = (get-process -ComputerName Dummyserver -Name Winword -ErrorAction
SilentlyContinue |where-object { $_.Count -gt 0})| Out-String
if($winwords -eq ""){
$winwords = "No Instances"
}
Send-MailMessage -To "Dummyemail.co.uk" -From " Dummyemail.co.uk" -Subject "WinWord
Check" -SmtpServer " Dummy.priv" -Body $winwords

Powershell Script to restart Windows Service If it is Down and send email

I have a PowerShell script which monitors the status of Windows services on multiple servers. Can someone help me with few modification where script checks the status and restarts the service if its not running? I would also like to send one consolidated email.
Code Below
$servers = Get-Content C:\servers.txt
$Servers | ForEach-Object {
invoke-command -ComputerName $_ -Scriptblock {Get-Service W3SVC}
}| Out-File C:\Result.txt
Help is appreciated.
I modified te script again and its working for me now.
#$Services=Get-content C:\Services.txt
$Servers=get-content C:\servers.txt
$SMPTServer = "smtp.ac.com"
$result = "The following service restarted:`n" # default output
$Servers|Foreach-Object{
$result += Invoke-Command -ComputerName $_ -ScriptBlock { # add output of scriptblock to $result
$CompName = (Get-WmiObject -Class Win32_ComputerSystem).Name
(Get-Service -Name Splunkd)| #Get the services running on all servers
Where-Object{$_.Status -eq "Stopped"}| #Which status is equal stopped
Foreach-Object{
if($_.Status -eq "Stopped")
{
Write-Output "`n -Service:- Splunkd is Down on Server $CompName - Service Splunkd on Server $CompName Restarted Successfully `n" # any action is added to output
$_.(Start-Service Splunkd) #try to start
#Start-Sleep -Seconds 60; #wait one minute
#$_.Refresh(); #refresh then service to update status
}}}}
if ($result -ne "The following service restarted:`n") { # If any action was taken send mail with $result
send-mailmessage -to "xx#xx.com" -from "abc#bc.com" -subject "Splunkd Service Restarted Alert" -Body $result -SmtpServer $SMPTServer
}

App_Pool_Alert Powershell Script

I have written a power shell script which is used to monitor the status of IIS app pools. With current method whenever any pool goes down it throws me an alert that pool is stopped and after that it starts the pool again send email stating that pool is up. Since i have around 50 servers so number of mails are coming in bulk which causes spam sometimes. Could some one help me here so that script will scan the pool directory and place the result in a text/html file and send me the list that these pools are down in mail. Please find script below:-
###################################Declear Servers in text file##############################################
$Servers = Get-Content C:\Users\Desktop\server.txt
################ Scans each server and import IIS web-administration module##################################
$Servers | ForEach-Object {
Invoke-Command -ComputerName $_ -ScriptBlock {
Import-Module WebAdministration
cd IIS:/AppPools
$CompName = (Get-WmiObject -Class Win32_ComputerSystem).Name
$ApplicationPools = dir
foreach ($item in $ApplicationPools)
{
$ApplicationPoolName = $item.Name
$ApplicationPoolStatus = Get-WebAppPoolState $ApplicationPoolName
If($ApplicationPoolStatus.value -eq "Stopped")
{
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool:- $ApplicationPoolName is Down on $CompName " -Body "$ApplicationPoolName is down. Please check IIS/Event logs for RCA." -SmtpServer ###########
Start-WebAppPool -Name $ApplicationPoolName
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool:- $ApplicationPoolName is Up on $CompName " -Body "$ApplicationPoolName is Up and running fine." -SmtpServer #############
}
}
}}
##################################### End of Script ##########################################################
This is how I would rewrite the script:
###################################Declear Servers in text file##############################################
$Servers = Get-Content C:\server.txt
################ Scans each server and import IIS web-administration module##################################
$SMPTServer = "mail.server.com"
$result = "The following application pools were restarted:`n`n" # default output
$Servers | ForEach-Object {
$result += Invoke-Command -ComputerName $_ -ScriptBlock { # add output of scriptblock to $result
Import-Module WebAdministration
cd IIS:/AppPools
$CompName = (Get-WmiObject -Class Win32_ComputerSystem).Name
$ApplicationPools = dir
foreach ($item in $ApplicationPools)
{
$ApplicationPoolName = $item.Name
$ApplicationPoolStatus = Get-WebAppPoolState $ApplicationPoolName
If($ApplicationPoolStatus.value -eq "Stopped")
{
Write-Output "Server $CompName - Application pool $ApplicationPoolName is Down - Restarting`n" # any action is added to otput
Start-WebAppPool -Name $ApplicationPoolName
}
}
}
}
if ($result -ne "The following application pools were restarted:`n`n") { # If any action was taken send mail with $result
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool Maitenance" -Body $result -SmtpServer $SMPTServer
}
##################################### End of Script ##########################################################
First define a $result variable, in this case just a string.
Withing your scriptblock, you can write anything to piped output using Write-Output. This output is returned from Ivoke-Command and added to the $result variable.
At the end of your script check if $result variable has changed and send it as a body of an email if required.

Get PrimaryStatus of DCIM_PhysicalDiskView and Put it in a variable in Powershell

I am trying to use the primaryStatus from the DCIM_PhysicalDiskView and compare it to 3 (degraded hard disk). If there is a match, an email will be sent to notify the admin. Here is the code:
$computerNames = Get-Content -Path C:\scripts\nameTest.txt
foreach ($computer in $computerNames) {
write-host "$computer"
$value = "3"
$smtpserver = "mailserver.xxxx.com" # your mail server here
$smtpFrom = "xx#xxxx.com" # your from address, mail server will most likely allow any
$smtpTo = "xx#xxxx.com" #your email address here. can also be an array and will send to all
$MessageSubject = "Testing Failed Disk in $computer" #whatever you want the subject to be.
gwmi -Namespace root\dcim\sysman -computername $computer -Class DCIM_PhysicalDiskView | ForEach {$name = $_.Name; $primaryStatus = $_.PimaryStatus}
if( $primaryStatus -contains $value )
{
Send-MailMessage -SmtpServer $smtpserver -from $smtpFrom -to $smtpto -subject $messageSubject
Write-Host "error message sent"
}
}
My problem is that the command is not piping to the foreach. The $name and $primaryStatus are staying null, therefore not going through the if statement.
Any help on this will be greatly appreciated. Thanks!
The below is your code with the braces changed for the foreach loop. Note that you will still need to have the closing brace from your opening foreach-object.
gwmi -Namespace root\dcim\sysman -computername $computer -Class DCIM_PhysicalDiskView | ForEach-Object {
$name = $_.Name
$primaryStatus = $_.PrimaryStatus
if( $primaryStatus -eq $value )
{
Send-MailMessage -SmtpServer $smtpserver -from $smtpFrom -to $smtpto -subject $messageSubject
Write-Host "error message sent"
}
}
Fixed the typo for $_.PrimaryStatus as well. Is $primaryStatus an array? -Contains only works with arrays. I think you wanted -eq? I dont have access to that namespace so i cannot test my theory. Also, I think that you could change this a little with a Where-Object.
gwmi -Namespace root\dcim\sysman -computername $computer -Class DCIM_PhysicalDiskView |
Where-Object { $primaryStatus -eq $value } | ForEach-Object{
Send-MailMessage -SmtpServer $smtpserver -from $smtpFrom -to $smtpto -subject $messageSubject
Write-Host "error message sent"
}
disclaimer: I do not have that namespace so I cannot test this but the logic looks sounds so it should work.