【ツールの概要】
・Powershellだけで、指定フォルダ内のファイルの中身(テキストファイル想定)を検索して、該当するファイルを圧縮してメール送信します。
・Powershellで完結することを意識しています()
【環境(使っている環境)】
・Windows Server2008
・Powershell ver5.1以降(必須、Compress-archiveが効かない)
【ソース(WordCheck.ps1)】
Param( $targetcfgfile ) # ■■■■■ログfunction $MSG{INF,WRN,ERR,CRT etc..}■■■■■ function logwrite($MSG, $INFO, $NAME, $outoputfile) { $NOW = Get-Date -Format G Write-Output "[ $NOW ][ $MSG ][ $NAME ] $INFO" | Out-File -Append $outoputfile -encoding Default } # ■■■■■変数設定■■■■■ $CWD = Split-Path $MyInvocation.MyCommand.Path -parent $WDCHKLOG = $CWD + "\log\WordCheck.log" logwrite "INF" "This script start." "_________" $WDCHKLOG # ■■■■■メール送信function読込(SendmailbyPS.ps1)■■■■■ $MAILPRG = $CWD + "\SendmailbyPS.ps1" If (Test-Path $MAILPRG) {} else { logwrite "CRT" "SendmailbyPS.ps1 not existed." "_________" $WDCHKLOG exit -1 } . ($MAILPRG) # ■■■■■設定XML読込(引数パス)■■■■■ foreach ($pathdata in $([xml](Get-Content $targetcfgfile)).config.pathdata) {} $logpattern = $pathdata.name logwrite "INF" "xmlfile loaded.[$targetcfgfile]" $logpattern $WDCHKLOG # ■■■■■検索対象フォルダファイルリスト作成■■■■■ $tarfilelist = $pathdata.tmpfilelist Write-Output "" | Out-File $tarfilelist -encoding String $nowArray = Get-ChildItem $pathdata.path -Name Get-ChildItem $pathdata.path | Sort-Object { $_.LastWriteTime } | ForEach-Object -Begin {$array = @()} -Process { $array += $_.Name + "`t" + $_.LastWriteTime} -End { Write-Output $array | Out-File -Append $tarfilelist -encoding String} # ■■■■■キーワードを含むログ抽出、コピー退避、配列格納処理■■■■■ $arrWDF = @() for ($i = 0; $i -lt $nowArray.Length; $i++) { $tarfile = $pathdata.path + $nowArray[$i] $WRDFCount = (Select-String -path $tarfile -pattern $pathdata.keyword).Count if ($WRDFCount -gt 0) { # 退避フォルダにない場合の処理(新規ファイル)。$existcheckにはコピー先ファイルのフルパスが入る。 $existcheck = $pathdata.sendfol + $nowArray[$i] If (Test-Path $existcheck) {} else { Copy-Item $tarfile -Destination $existcheck logwrite "INF" "File copied. This file contains `"$($pathdata.keyword)`" . File=$existcheck" $logpattern $WDCHKLOG $arrWDF += $existcheck } } } # ■■■■■異常ログzip圧縮・メール送信処理■■■■■ if ($arrWDF.Length -gt 0) { # ■■■■■(XML指定)zipparentpath直下のforCompressフォルダに対象ログをコピー■■■■■ $forLocalCopy = $pathdata.zipinsidepath for ($i = 0; $i -lt $arrWDF.Length; $i++) { $localfname = $forLocalCopy + $(Get-ChildItem $arrWDF[$i]).Name Copy-Item $arrWDF[$i] -Destination $localfname } # ■■■■■ファイルをすべてzip化する■■■■■ $zipfname = $pathdata.zipparentpath + $(Get-Date -UFormat "%Y%m%d%H%M") + $pathdata.keyword + '.zip' If (Test-Path $zipfname) { logwrite "CRT" "ZIPFile already existed. Machine Time was crasehd? Path=$zipfname" $logpattern $WDCHKLOG } else { $tarCmpFile = $forLocalCopy + $pathdata.filetype try { compress-archive -Path $tarCmpFile -DestinationPath $zipfname } catch { logwrite "CRT" "Files-compress Failed." $logpattern $WDCHKLOG $CompressResult = 'error' } } if ($CompressResult -eq 'error') { # ■■■■■メール送信処理(圧縮エラー時)■■■■■ $Body = $pathdata.errbody $sendresult = SendmailbyPS $pathdata.address $pathdata.cc $pathdata.fromaddress $pathdata.subject $Body $tarfilelist $pathdata.mailxmlpath if ($sendresult -eq 'OK' ) { logwrite "INF" "Mail was sended. Attachmentfile=$tarfilelist" $logpattern $WDCHKLOG } else { logwrite "CRT" "Mail couldnot send. Errormessage=$sendresult" $logpattern $WDCHKLOG } } else { # ■■■■■メール送信処理(正常、キーワードファイル存在時)■■■■■ $Body = $pathdata.body1 + $arrWDF.Length + $pathdata.body2 $sendresult = SendmailbyPS $pathdata.address $pathdata.cc $pathdata.fromaddress $pathdata.subject $Body $zipfname $pathdata.mailxmlpath if ($sendresult -eq 'OK' ) { logwrite "INF" "Mail was sended. Attachmentfile=$zipfname" $logpattern $WDCHKLOG } else { logwrite "CRT" "Mail could not send. Errormessage=$sendresult" $logpattern $WDCHKLOG } # ■■■■■送信済ファイル削除(tmpフォルダのため)■■■■■ del $tarCmpFile } } else { logwrite "INF" "Target file contain taregt word is not existed." $logpattern $WDCHKLOG } logwrite "INF" "This script ended." $logpattern $WDCHKLOG
【ソース(SendmailbyPS.ps1)】
function SendmailbyPS($address, $Cc, $Fromaddress, $Subject, $Body, $attachment, $mailcfgpath) { $Mailconf_info = [xml](Get-Content $mailcfgpath) foreach ($data in $Mailconf_info.config.data) {} $MailSv = $data.MailSv $Port = $data.Port $Encode = $data.Encode $uid = $data.uid $pwd = $data.pwd $MailSv = $data.MailSv #Credential $pwd = $pwd | ConvertTo-SecureString -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential $uid, $pwd #Send Mail try { Send-MailMessage ` -To $address ` -Cc $cc ` -From $Fromaddress ` -SmtpServer $MailSv ` -Credential $cred ` -UseSsl ` -Encoding $Encode ` -Port $Port ` -Subject $Subject ` -Body $Body ` -Attachments $attachment $result = 'OK' } catch { $ErrorMessage = $_.Exception_Message $result = $ErrorMessage + $LASTEXITCODE } finally { echo $LASTEXITCODE } return $result }
【設定ファイル(~~.xml)】
<?xml version="1.0"?> <config> <pathdata> <name>ログ用の名前</name> <keyword>MAILER-DAEMON</keyword> <path>\\対象フォルダパス\</path> <sendfol>\\抽出ファイル格納パス\</sendfol> <tmpfilelist>D:\ローカルどこか\WordSearch\tmp\MDchecklist.txt</tmpfilelist> ←該当ファイルリスト出力用 <zipparentpath>D:\ローカルどこか\WordSearch\tmp\</zipparentpath> ←zipが吐かれてたまっていく場所です。 <zipinsidepath>D:\ローカルどこか\WordSearch\tmp\forCompress\</zipinsidepath> ←zipにするために一時的にコピーされる場所です。 <mailxmlpath>D:\ローカルどこか\WordSearch\etc\mailcfg.xml</mailxmlpath> ←SendmailbyPSのための設定ファイルの場所です。 <filetype>*.txt</filetype> ←メールで送るファイルの種類です <address>メールTo</address> <cc>メールCc</cc> <fromaddress>メールFromt</fromaddress> <subject>メール件名</subject> <body1>なんちゃら's mail was recieved because the sent e-mail was something wrong. There are </body1> ←メール本文1です(文法気にしないで) <body2> mails found as alert mails.</body2> <errbody>Compress error</errbody> </pathdata> </config>
【使用方法】
・上記のスクリプトおよび設定ファイルは、MAILER-DAEMONを検索するために作られたので、そんな感じになっています。
・ps1ファイルは2つ同じ場所におき、powershell.exe -Command (フルパス)WordCheck.ps1 (フルパス)設定xmlでタスクに登録したりします。
【説明】
・ログは一つです。
・初心者にはちょっと厳しいです。また、よくないところもあるかと思います。(変数の多用とか命名とか)
【総評】
このスクリプトはあるフォルダ内にはテキストファイルがたまに吐かれるけれども、そのファイルの中身でアラートを発したいというのがきっかけでした。
質問などは適当にしてくださったら適当に答えると思います!ちなみに一番頑張ったのはこ↑こ↓
Get-ChildItem $pathdata.path | Sort-Object { $_.LastWriteTime } | ForEach-Object -Begin {$array = @()} -Process { $array += $_.Name + "`t" + $_.LastWriteTime} -End { Write-Output $array | Out-File -Append $tarfilelist -encoding String}