How check Updated File

Hi,
I was trying to search a string in logs that will update continuously in every second.
So i wrote the code to search the string if the string found in log it will triger an email.
and created the tasks in task scheduler to run the script in every 5 min.
But the issue is that if script found the “string” in log it will trigger mail in every 5 min continuoisly beause script is checking whole log file everytime.
Can you please suggest me is this possible to point last script checked the logs till the point and next time script will run and do not check whole log file it will check only from last script done.

$string = gci -path c:\folder\lofile.log | sort {$_.LastWriteTime} | select -last 1 | select-string -pattern “string”

#####################################################################

$fromaddress = “@gmail.com"
$toaddress = "
@gmail.com
$Subject = “testing”
$body = "Hi Team`
We got an error " +
$string +
“Please check”
$attachment = “c:\folder\lofile.log”
$smtpserver = “smtp.gmail.com

####################################

$message = new-object System.Net.Mail.MailMessage
$message.From = $fromaddress
$message.To.Add($toaddress)
$message.IsBodyHtml = $True
$message.Subject = $Subject
$attach = new-object Net.Mail.Attachment($attachment)
$message.Attachments.Add($attach)
$message.body = $body
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$smtp.Send($message)

Here is one way. It will store the line number of the last match in a file to persist the last location found between script runs and on subsequent runs only send if a newer match is found.
My apologies for the ugly code but hopefully it helps

$trackerpath = "D:\test\tracker.txt"
if(test-path $trackerpath){[int]$tracker = Get-Content -Path $trackerpath}else{$tracker = 0}
$string = gci -path c:\folder\lofile.log | sort {$_.LastWriteTime} | select -last 1 | select-string -pattern "string"
if($string){
    Foreach($return in $string){
        if($return.LineNumber -gt $tracker){
            $return.LineNumber|Out-File $trackerpath -Force
            $sendemail = $true
        }
    }
}
If($sendemail){
    #####################################################################
    
    $fromaddress = "*************@gmail.com"
    $toaddress = "*************@gmail.com"
    $Subject = "testing"
    $body = "Hi Team`
    We got an error " +
    $string +
    "Please check"
    $attachment = "c:\folder\lofile.log"
    $smtpserver = "smtp.gmail.com"
    
    ####################################
    
    $message = new-object System.Net.Mail.MailMessage
    $message.From = $fromaddress
    $message.To.Add($toaddress)
    $message.IsBodyHtml = $True
    $message.Subject = $Subject
    $attach = new-object Net.Mail.Attachment($attachment)
    $message.Attachments.Add($attach)
    $message.body = $body
    $smtp = new-object Net.Mail.SmtpClient($smtpserver)
    $smtp.Send($message)
}

ThankS it Works

Hi Jonathan,

script works perfect for first time, then i edited the source file (logfile) but unable to save the changes because some other program is using the file. it means that once we run the script log file will update or not ?

Please apologies, if i am unable to convey my problem correctly :slight_smile:

Yes.

I am also facing same issue here, it works only for one file but it is not possible that one file to save all logs.
suppose the log file name filelog.log it will create every day at starting on day means at 0000/12Am every day and the previous log file automatically rename by the date like filelog_03_21_2016. the script ran suppose at 11:30 PM and it checked the logs till line no. 200 then again script run at 12 Am means here the new file generate an the script will check the logs after line no. 200.

So i tried to write the code for to compare time is greater than 12AM and less than 1230 Am so that after the script run between this time it will delete the line number file and create a new file and check the log from first line.

$date = (get-date -UFormat %H%M).ToString()
$a = “0000”
$b = “0030”
$date.GetType()
if($date -ge $a -le $b)
{
remove-item -path D:\filelog.log
}

Can you please suggest what can i do here because it is comparing string size not value of time.
Thanks

You are correct that the sample will only work for one file. The concept can support multiple files but how you track the state of the checks will drive the script. You could add additional information to the tracking file which could be read by the script to determine when to reset.
Or as you suggest, adding a window of time into the script in which to delete the tracking file is and option. But your original question had a requirement to check the file every 5 minutes and if you use a 30 minute window in which to reset each morning the script has the potential to recheck the entire file each time it is run during that window of time.
Another option if the log file includes time stamps they could be added to the tracking info to ensure that if the log resets you start back at the beginning of the file.
You have to understand that what you are trying to accomplish requires a very clear set of requirements in order to be successful.

As to your question of how to delete the file if the time is between 12 AM and 12:30 AM

$date = get-date
if($date.TimeOfDay.TotalHours -le .5){remove-item -path D:\filelog.log}

Thanks That Works for me to reset file.
Another issue is that you have given the code to get the line number only when the match will found, is there any other way to check the log files till last line not by matching any string and then check the string “error” is occur if it occurs then it will mention that error in mail and next when the script run it will capture the line number from last updated line number to till and it never repeat the same string “error” for same log file.

Thanks

The same technique used to check for “string” can be used to check for “error”. Why don’t you review the code and try to modify it to accomplish that and ask questions if you need help getting it working.

I was trying to get the all errors occurs and then send a mail with mentioning those error. but it was only mentioning a last error. i tried below code to get the output but it was not working.
it is possible to get error every time when the script run for example i ran the script at 12AM and got an error on linenumber 200 and but here it will mention only error occurs on linenumber 200 but i need all error before that. then next script run after 30 min means at 1230Am so this time it will check for error from linenumner 201 to last updated line numbers and mention all error occurs between linenumber 201 - last updated line.
$trackerpath = “D:\test\tracker.txt”
if(test-path $trackerpath){[int]$tracker = Get-Content -Path $trackerpath}else{$tracker = 0}
$string = gci -path c:\folder\lofile.log | sort {$_.LastWriteTime} | select -last 1 | select-string -pattern “string”
if($string){
Foreach($return in $string){
if($return.LineNumber -gt $tracker){
$return.LineNumber|Out-File $trackerpath -Force
$sendemail = $true
}
}
}
If($sendemail){
#####################################################################

$fromaddress = "*************@gmail.com"
$toaddress = "*************@gmail.com"
$Subject = "testing"
$body = "Hi Team`
We got an error " +
$return +
"Please check"
$attachment = "c:\folder\lofile.log"
$smtpserver = "smtp.gmail.com"

####################################

$message = new-object System.Net.Mail.MailMessage
$message.From = $fromaddress
$message.To.Add($toaddress)
$message.IsBodyHtml = $True
$message.Subject = $Subject
$attach = new-object Net.Mail.Attachment($attachment)
$message.Attachments.Add($attach)
$message.body = $body
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$smtp.Send($message)

}

Thanks,

Issue Resolved…