Search code examples
powershellscriptingwatchtailselect-string

Use PowerShell's type -wait with select-string to Real-Time Monitor an Application Log for a Condition and Execute an Action (like tail -f or watch)


I am trying to use PowerShell's type -wait command to monitor a log file in real time on Windows in the same way that I would use tail -f on Linux, and I want to pipe the file to another command - select-string, like grep - that will trigger an action based on a condition. On Linux, I would use watch to accomplish what I'm trying to do.

In the following example, I am trying to print the phrase "You caught a critter!" whenever a new line, which contains the string "status=Caught", is written to the log file.

while (1) {if (type -wait "$env:USERPROFILE\AppData\Roaming\CritterCatcherApp\Logs\CritterBag-170118.log" | select-string -quiet "state=Caught") {write-host "You caught a critter!"} else {continue}}

Please note that the -quiet argument for the select-string command returns True. Actually, in this example, it only returns True one time, when I first run the command, as the log file has existing lines that contain the string "status=Caught".

I do need to somehow overlook the existing strings (or, e.g., rotate the log files), but right now, the issue is that I need the PowerShell script to not only continue to tail the file, but I also need it to continue to evaluate whether each new line that is written to the file contains the given string. Then, if the string is present, I need to execute an arbitrary action, like print a line; else, continue listening for the string.

The following post indicates that the -wait argument is an option for the Get-Content cmdlet: How to monitor a windows log file in real time? . I am not sure if I should expect -wait to work with a foreach loop, as described in this post: In Powershell can i use the select-string -quiet switch within a foreach statement .

How can I modify the above PowerShell script to tail a log file and execute an action for each new line with a given string, and continue to tail the file and evaluate new lines as they are written?


Solution

  • You can do it on the pipeline with Where-Object (?) and ForEach-Object (%):

    Get-Content file -wait | ? { $_ -match "status=Caught" } | % { Write-Host "You caught a critter!" }
    

    Each time status=Caught is detected in the file, the Write-Host in the ForEach-Object will execute