Raportowanie skryptów

Kiedyś usłyszałem powiedzenie, iż dobry administrator to leniwy administrator. Prawdziwi sens tego powiedzenia zaczyna się sprawdzać w przypadku skrypciaży. Właśnie dzięki takim narzędziom jak PowerShell możliwe jest zautomatyzowanie większej części prac administracyjnych. Niemniej jednak największym problemem automatyzacji zadań, zwykle jest brak późniejszej kontroli nad nimi. Z własnych obserwacji mogę stwierdzić, iż raz skonfigurowany skrypt pracujący np. w harmonogramie zadań, działa tak długo dopóki jakiś składnik systemu wykorzystywany w skrypcie nie zmieni się, a wtedy mogą zacząć się problemy. Bez choćby prowizorycznego mechanizmu monitorowania może to być przykre w skutkach.

Najprostszym takim mechanizmem jest wykorzystywanie powiadomienia np. na email z prostym raportem o stanie wykonanego zadania. Dziś właśnie chciałbym zaprezentować jak stworzyć taki system raportowania. Choć stworzyć to za dużo powiedziane gdyż do tego celu mamy już gotowe cmdlety.

Ogólnie najprostszym sposobem wysłania maila z PowerShella jest użycie Send-MailMessage.

Send-MailMessage -from "mg1@contoso.com" -to "mg2@contoso.com" `
-subject "Temat wiadomości" -body "Treść wiadomości" `
-smtpServer "contoso.com" –Encoding ([System.Text.Encoding]::UTF8)

Jedynym minusem jest podawanie kodowania w odpowiednim typie danych [System.Text.Encoding]::UTF8, tak aby móc przetworzyć polskie znaki (przykład na bazie Outlooka).

OK, możemy wysłać na sztywno wiadomość, ale co jak wynik będzie generowany dynamicznie na podstawie wcześniej wykonanych zadań, np. wyślijmy raport 10 najbardziej obciążających system procesów.

$report = Get-Process |
Sort-Object WorkingSet -Descending |
Select-Object -First 10
$date = (Get-Date).ToString()
Send-MailMessage -from "mg1@contoso.com" -to "mg2@contoso.com" `
-subject "Raport $date" -body $report -smtpServer contoso.com

Tutaj rodzi nam się pierwszy problem, gdyż wiadomość email jest przekazywana jako tekst. Natomiast wynik naszego raportu jest przekazywany jako obiekt PoweShella.

Send-MailMessage : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Body'. Określona
 metoda nie jest obsługiwana.
At line:2 char:30
+ -subject "Raport $date" -body <<<<  $report -smtpServer contoso.com
    + CategoryInfo          : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.SendMailMessage

Dlatego musimy pamiętać, aby treść wysyłana w raporcie była reprezentowana jako obiekt typu String. Można tego dokonać na kilka sposobów, ale najprościej chyba jest użyć cmdletu Out-String

$report = Get-Process |
Sort-Object WorkingSet -Descending |
Select-Object -First 10 |
Out-String
$date = (Get-Date).ToString()
Send-MailMessage -from "mg1@contoso.com" -to "mg2@contoso.com" `
-subject "Raport $date" -body $report -smtpServer contoso.com

Drugi problem możemy zauważyć na powyższym zrzucie ekranu. Wiadomość jest przekazana jako zwykły tekst co powoduje „rozjechanie” się treści i zazwyczaj jest ona mało czytelna.

Wyjściem z tej sytuacji jest przesyłanie wiadomości w formie HTML’a. Spróbujmy zatem:

$report = Get-Process |
Sort-Object WorkingSet -Descending |
Select-Object -First 10 |
Out-String
$date = (Get-Date).ToString()
Send-MailMessage -from "mg1@contoso.com" -to "mg2@contoso.com" `
-subject "Raport $date" -body $report -smtpServer contoso.com -BodyAsHtml

Jak widzimy nawet jest jeszcze gorzej. Dalczego? Mianowicie parametr BodyAsHtml służy tylko do zmiany flagi czy wiadomość ma być wysłana jako tekst czy jako Html, poprzez dodanie podstawowego nagłówka html’a do wiadomości. Niestety całą resztę konwersji raportu musimy przeprowadzić we własnym zakresie.

Nie ma co jednak panikować, by tego dokonać wystarczy posłużyć się cmdletem ConvertTo-Html. Należy jednak pamiętać, aby wybrać jakie atrybuty chcemy przekazać w raporcie inaczej przekonwertowany zostanie cały obiekt co może zaśmiecić nam raport.

$report = Get-Process |
Sort-Object WorkingSet -Descending |
Select-Object -First 10 |
ConvertTo-Html Handles, NPM, PM, VM, WS, Id, Name |
Out-String
$date = (Get-Date).ToString()
Send-MailMessage -from "mg1@contoso.com" -to "mg2@contoso.com" `
-subject "Raport $date" -body $report -smtpServer contoso.com -BodyAsHtml

W takiej formie mamy już całkiem przyzwoity mechanizm monitorowania, który możemy zaimplementować do skryptu.

Teraz część dla bardziej zaawansowanych. Aby cały zapis raportu wyglądał bardziej profesjonalnie możemy posłużyć się formatowaniem kodu HTML przy pomocy CSS. By tego dokonać tworzymy blok skryptu css, a następnie podpinamy go do nagłówka podczas konwertowania obiektu PowerShella do Html.

$css = @"
<style>
<!--
     table {
        font-family: Verdana;
        border-style: dashed;
        border-width: 1px;
        border-color: #FF6600;
        padding: 5px;
        background-color: #FFFFCC;
        table-layout: auto;
        text-align: center;
        font-size: 8pt;
        }
     table th {
        border-bottom-style: solid;
        border-bottom-width: 1px;
        }
     table td {
        border-top-style: solid;
        border-top-width: 1px;
        }
-->
</style>
"@

$report = Get-Process |
	Sort-Object WorkingSet -Descending |
	Select-Object -First 10 |
	ConvertTo-Html Handles, NPM, PM, VM, WS, Id, Name -Head $css |
	Out-String
$date = (Get-Date).ToString()

Dodatkowo cały zapis parametrów możemy zapisać w bardziej przejrzysty sposób.

$MailMessage = @{
	To = "mg2@contoso.com"
	From = "mg1@contoso.com"
	Subject = "Raport $date"
	Body = $report
	Smtpserver = "contoso.com"
}

Send-MailMessage @MailMessage -BodyAsHtml

Dodatkowo, aby do wiadomości dołączyć załącznik wykorzystujemy parametr –Attachments wraz z podaniem ścieżki do interesującego nas pliku.

Dla ciekawostki tylko, wiadomości email możemy wysyłać również w bardziej „programistyczny” sposób, a mianowicie z ręcznym wykorzystaniem klas .NETa Net.Mail.SmtpClient oraz Net.Mail.MailMessage.

$SmtpServer = "contoso.com"
$SmtpClient = New-Object Net.Mail.SmtpClient($SmtpServer)
$Subject = "Temat wiadomości"
$Body = "Treść wiadomości"
$EmailSender = "mg1@contoso.com"
$EmailRecipient = "mg2@contoso.com"
$SmtpClient.Send($EmailSender, $EmailRecipient, $Subject, $Body)

Źródła:
http://gallery.technet.microsoft.com/scriptcenter/c63025ef-645d-4efe-a4c3-bc126cb939e8

Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s