{"id":1225,"date":"2015-09-24T21:13:03","date_gmt":"2015-09-24T19:13:03","guid":{"rendered":"http:\/\/blog.langlitz-it.de\/?p=1225"},"modified":"2017-08-10T12:55:18","modified_gmt":"2017-08-10T10:55:18","slug":"powershell-logfiles-sortieren-parsen-und-mehr","status":"publish","type":"post","link":"https:\/\/www.langlitz-it.de\/?p=1225","title":{"rendered":"PowerShell &#8211; Logfiles sortieren, parsen und mehr"},"content":{"rendered":"<p>Es gibt viele Parser, die Sie nutzen k\u00f6nnen, um <em>Logfiles<\/em> auszuwerten. Allerdings bietet die <em>PowerShell<\/em> schon von Haus aus alles, was Sie ben\u00f6tigen.<\/p>\n<h2>Z\u00e4hlen, sortieren, &#8230;<\/h2>\n<p>Fangen wir mal mit dem Sortieren und &#8220;Z\u00e4hlen&#8221; von Logfiles an. Ich m\u00f6chte exemplarisch wissen, an welchen Tagen wie viele <em>Logfiles<\/em> erstellt wurden. Im Beispiel befassen wir uns mit den <em>SMTP Send\/Receive<\/em> Logs eines <em>Exchange 2010 HubServers<\/em>. Das Ganze l\u00e4\u00dft sich nat\u00fcrlich auf alle Files anwenden.<\/p>\n<p>Wie jedes Objekt, bringt auch jede Datei <em>Properties<\/em> mit, die sich\u00a0weiter verarbeiten lassen. Um sich diese ansehen zu k\u00f6nnen, w\u00e4hlt man eine Datei und gibt sich alle <em>Properties<\/em> aus. Wir bleiben beim Beispiel der <em>Exchange Logfiles<\/em> und sehen uns die <em>Properties<\/em>\u00a0an:<\/p>\n<p><em>Get-ChildItem -recurse -Include *recv201508* |select *<\/em><\/p>\n<p><em>PSPath : Microsoft.PowerShell.Core\\FileSystem::C:\\Program Files\\Microsoft\\Exchange Server\\V14\\TransportRoles<\/em><br \/>\n<em> \\Logs\\ProtocolLog\\SmtpReceive\\RECV20150831-1.LOG<\/em><br \/>\n<em>PSParentPath : Microsoft.PowerShell.Core\\FileSystem::C:\\Program Files\\Microsoft\\Exchange Server\\V14\\TransportRoles<\/em><br \/>\n<em> \\Logs\\ProtocolLog\\SmtpReceive<\/em><br \/>\n<em>PSChildName : RECV20150831-1.LOG<\/em><br \/>\n<em>PSDrive : C<\/em><br \/>\n<em>PSProvider : Microsoft.PowerShell.Core\\FileSystem<\/em><br \/>\n<em>PSIsContainer : False<\/em><br \/>\n<em>VersionInfo : File: C:\\Program Files\\Microsoft\\Exchange Server\\V14\\TransportRoles\\Logs\\ProtocolLog\\Sm<\/em><br \/>\n<em> tpReceive\\RECV20150831-1.LOG<\/em><br \/>\n<em> InternalName:<\/em><br \/>\n<em> OriginalFilename:<\/em><br \/>\n<em> FileVersion:<\/em><br \/>\n<em> FileDescription:<\/em><br \/>\n<em> Product:<\/em><br \/>\n<em> ProductVersion:<\/em><br \/>\n<em> Debug: False<\/em><br \/>\n<em> Patched: False<\/em><br \/>\n<em> PreRelease: False<\/em><br \/>\n<em> PrivateBuild: False<\/em><br \/>\n<em> SpecialBuild: False<\/em><br \/>\n<em> Language:<\/em><\/p>\n<p><em>BaseName : RECV20150831-1<\/em><br \/>\n<em>Mode : -a&#8212;<\/em><br \/>\n<em>Name : RECV20150831-1.LOG<\/em><br \/>\n<em>Length : 9783413<\/em><br \/>\n<em>DirectoryName : C:\\Program Files\\Microsoft\\Exchange Server\\V14\\TransportRoles\\Logs\\ProtocolLog\\SmtpReceive<\/em><br \/>\n<em>Directory : C:\\Program Files\\Microsoft\\Exchange Server\\V14\\TransportRoles\\Logs\\ProtocolLog\\SmtpReceive<\/em><br \/>\n<em>IsReadOnly : False<\/em><br \/>\n<em>Exists : True<\/em><br \/>\n<em>FullName : C:\\Program Files\\Microsoft\\Exchange Server\\V14\\TransportRoles\\Logs\\ProtocolLog\\SmtpReceive\\RECV2015<\/em><br \/>\n<em> 0831-1.LOG<\/em><br \/>\n<em>Extension : .LOG<\/em><br \/>\n<strong><em>CreationTime : 31.08.2015 02:00:01<\/em><\/strong><br \/>\n<em>CreationTimeUtc : 31.08.2015 00:00:01<\/em><br \/>\n<em>LastAccessTime : 31.08.2015 02:00:01<\/em><br \/>\n<em>LastAccessTimeUtc : 31.08.2015 00:00:01<\/em><br \/>\n<em>LastWriteTime : 01.09.2015 02:00:02<\/em><br \/>\n<em>LastWriteTimeUtc : 01.09.2015 00:00:02<\/em><br \/>\n<em>Attributes : Archive<\/em><\/p>\n<p>Als eine <em>Fileinfo<\/em> steht die <em>Creationtime<\/em> zur Verf\u00fcgung. Wenn Sie nun, die Logs der letzten 14 Tage sehen m\u00f6chten, k\u00f6nnen Sie dies mit der folgenden Abfrage realisieren:<\/p>\n<p><em>Get-ChildItem |? {$_.creationtime -gt (get-date).adddays(-14)}<\/em><\/p>\n<p>Jetzt zur eigentlichen Anforderung, die Logfiles an den einzelnen Tagen zu z\u00e4hlen. Das erreichen Sie, wenn sie folgenden Befehl absetzen. Dieser liest in einer Schleife die Logfiles der letzten 14 Tage ein und addiert sie jeweils f\u00fcr einen Tag.<\/p>\n<p><em>-13..0 |% {$e=$_ ; ($Items |? {$_.CreationTime -gt (Get-Date).AddDays(-14)} |? {$_.CreationTime.Date -eq (Get-Date).AddDays($e).Date}).count}<\/em><\/p>\n<p>Das Ganze funktioniert zwar, ist aber f\u00fcr eine gro\u00dfe Anzahl von <em>Logfiles<\/em> absolut unpraktikabel. Abh\u00e4ngig von der Anzahl der <em>Logfiles<\/em>, kann es \u00e4u\u00dferst lange dauern, bis alle eingelesen sind. Der Grund daf\u00fcr ist, dass die Schleife 14 mal durchl\u00e4uft und bei jedem Durchlauf alle Files einliest, um dann zu erfassen welche f\u00fcr den entsprechenden Tag addiert werden m\u00fcssen. Optimieren kann man dies noch dadurch, dass einmalig alle <em>Files<\/em> in eine <em>Variable<\/em> eingelesen werden und die Datumspr\u00fcfung dann \u00fcber die <em>Variable<\/em> l\u00e4uft. Dazu werden zuerst alle <em>Files<\/em> der letzten 14 Tage eingelesen:<\/p>\n<p><em>$Items =\u00a0Get-ChildItem -recurse |? {$_.CreationTime -gt (Get-Date).AddDays(-14)}<\/em><\/p>\n<p>Dann lassen wir die Schleife \u00fcber die <em>Variable<\/em> laufen, was schon wesentlich schneller abl\u00e4uft:<\/p>\n<p><em>-13..0 |% {$e=$_ ; ($Items |? {$_.CreationTime -gt (Get-Date).AddDays(-14)} |? {$_.CreationTime.Date -eq (Get-Date).AddDays($e).Date}).count}<\/em><\/p>\n<p>Optimal ist diese L\u00f6sung aber immer noch nicht. Wenn wir bedenken, dass alle Files schon in einer Variablen stehen und alle Files das C<em>reationTime<\/em> <em>Property<\/em> mitbringen, kann die <em>Variable<\/em> einfach nach diesem <em>Property<\/em> mit G<em>roup-Object<\/em> gruppiert werden.<\/p>\n<p><em>$Items | % { $_.CreationTime.Date.ToShortDateString} | Group-Object |ft name,count -autosize<\/em><\/p>\n<p>Hierbei ist es wichtig, dass Sie das <em>Property $_.CreationTime.Date<\/em> ausw\u00e4hlen, da sonst die Uhrzeit mit ber\u00fccksichtigt wird. <em>$_.CreationTime.Date<\/em> liefert zwar auch eine Uhrzeit, aber diese ist immer leer, bzw. 00:00:00 und damit zum Gruppieren gleich.<\/p>\n<h2>Parsen<\/h2>\n<p>Nun bleiben wir bei den <em>SMTP Logs<\/em> des <em>Exchange Servers<\/em> und versuchen eine <em>eMail<\/em> zu finden.<\/p>\n<p>Wir wissen, dass irgendwann in den letzten 14 Tagen eine Mail an <em>blog@langlitz-it.de<\/em> gesendet wurde. Also suchen wir in den <em>Logfiles<\/em> nach diesem Empf\u00e4nger. Wir haben schon alle <em>Files<\/em> der letzten 14 Tage in der <em>Variablen<\/em> <em>$Items<\/em> eingelesen und k\u00f6nnen somit diese <em>Variable<\/em> weiter nutzen.<\/p>\n<p><em>$Items | Get-Content |? {$_ -like &#8220;*RCPT TO:&lt;blog@langlitz-it.de&gt;*&#8221;}<\/em><\/p>\n<p>Als Ergebnis erhalten wir die entsprechenden Eintr\u00e4ge in den <em>Logs<\/em>.<\/p>\n<p><em>2015-09-11T13:54:20.602Z,ServerName\\ConnectorName,08D27BC0FD7915C3,36,AbsendeIP:25,Empf\u00e4ngerIP:Port,&lt;,RCPT TO:&lt;blog@langlitz-it.de&gt;,<\/em><\/p>\n<p>Genau so gut k\u00f6nnen Sie nun auch die Anzahl der Mails der letzten 14 Tage suchen:<\/p>\n<p><em>($Items | Get-Content |? {$_ -like &#8220;*RCPT TO:&lt;blog@langlitz-it.de&gt;*&#8221;}).count<\/em><\/p>\n<p>Wenn Sie nur bestimmte Daten aus einem <em>Logfile<\/em> w\u00fcnschen, k\u00f6nnen Sie die einzelnen Zeilen auch noch <em>splitten<\/em>. Im Beispiel der <em>SMTP Logs<\/em> k\u00f6nnten Sie sich z.B. nur den Zeitstempel, die Empf\u00e4nger IP und die Empf\u00e4nger Adresse anzeigen lassen:<\/p>\n<p><em>$Items |Get-Content |? {$_ -like &#8220;*RCPT TO:&lt;blog@langlitz-it.de&gt;*&#8221;} |% {$_.split(&#8220;,&#8221;)[0,5,7]}<\/em><\/p>\n<p>Mit dem <em>Split<\/em> trennen Sie die Ergebniszeile, die durch ein <em>&#8220;,&#8221;<\/em> separiert ist auf und liefern in einem <em>Array<\/em> die Felder <em>[0] (Zeitstempel), [5] (Empf\u00e4nger IP:Port)<\/em> und <em>[7] (Empf\u00e4nger Mailadresse)<\/em> in einer Liste zur\u00fcck.<\/p>\n<p><em>2015-09-11T00:01:52.237Z<\/em><br \/>\n<em> Empf\u00e4ngerIP:Port<\/em><br \/>\n<em> RCPT TO:&lt;blog@langlitz-it.de&gt;<\/em><\/p>\n<p>Bei dieser Vorgehensweise sind prinzipiell keine Grenzen gesetzt.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Es gibt viele Parser, die Sie nutzen k\u00f6nnen, um Logfiles auszuwerten. Allerdings bietet die PowerShell schon von Haus aus alles, was Sie ben\u00f6tigen. Z\u00e4hlen, sortieren, &#8230; Fangen wir mal mit dem Sortieren und &#8220;Z\u00e4hlen&#8221; von Logfiles an. Ich m\u00f6chte exemplarisch &hellip; <a href=\"https:\/\/www.langlitz-it.de\/?p=1225\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[534,530,537,538,539,230,531,527,528,532,533,553,535,536,543,529],"_links":{"self":[{"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=\/wp\/v2\/posts\/1225"}],"collection":[{"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1225"}],"version-history":[{"count":27,"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=\/wp\/v2\/posts\/1225\/revisions"}],"predecessor-version":[{"id":2014,"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=\/wp\/v2\/posts\/1225\/revisions\/2014"}],"wp:attachment":[{"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.langlitz-it.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}