首页 > 解决方案 > 有没有办法在 Windows 中创建指向最新文件的链接/符号链接/快捷方式?继续跟踪最新的日志文件

问题描述

我搜索了高低,找到了如何在 *nix 中执行此操作,但没有关于 Windows。

我看到的第一个地方是 Tomcat 的 catalina.out,现在我想知道如何在 Windows 上做类似的事情:考虑创建日志文件的文件夹,如何创建一个读取 / 指向创建的最新日志的文件?

我认为 Powershell 解决方案可能是可能的,但老实说,我想不出或找到任何方法来做到这一点。

(编辑)你们投反对票至少可以发表评论告诉我我做错了什么或者我该如何改进这个问题?

(编辑)这里的想法是有一些方法来创建一个指向文件夹中最新日志文件的符号链接,因此程序可以始终监视同一个文件,无论最新文件是否更改其名称 - 就像tail -f catalina.out总是读取最新的 catalina 日志文件。

我能看到并且我想避免的唯一出路是编写一个可以监视文件夹的 powershell 脚本(https://superuser.com/questions/226828/how-to-monitor-a-folder- and-trigger-a-command-line-action-when-a-file-is-created)并动态创建指向找到的最新文件的符号链接(https://stackoverflow.com/a/11211005/1985023),然后将其设置为服务,因此它将始终在后台运行。

标签: windowspowershelllogging

解决方案


而不是寻找一个动态的自我更新符号链接(这将是非常麻烦的实现 - 请参阅问题评论中来自BACON的有用提示),您可以在PowerShell后台作业

  • 在一个循环中运行,该循环定期从后台作业中获取最新的日志文件行,该作业相当于 Unixtail -f通过Get-Content -Wait -Tail 10.

  • 如果找到新的日志文件,则终止前一个后台作业并为新的日志文件启动一个。

请注意,这依赖于定期轮询跟踪日志的后台作业。下面的代码允许您调整轮询间隔。
请注意,Get-Content -Wait它本身每秒都会轮询目标文件以进行更改。

这是代码;运行$VerbosePreference = 'Continue'以查看循环内部发生了什么:

$dir = 'C:\path\to\logs' # the log-file directory
$logFilePattern = '*.log' # wildcard pattern matching log files
$sleepIntervalMs = 1000  # how many msec. to sleep between getting new lines from the background job

Write-Host -ForegroundColor Green "Tailing the latest log(s) in $dir...`nPress any key to quit."
$currJob = $currLog = $null
while ($true) {

  # If the user pressed a key, clean up and exit.
  if ([console]::KeyAvailable) {
    $null = [console]::ReadKey($True) # consume the key - it will still have printed, though
    if ($currJob) { Remove-Job -Job $currJob -Force }
    break
  }

  # Get the latest lines from the current log from the background job.
  if ($currJob) {
    Write-Verbose "Checking for new lines in $newLog..."
    Receive-Job -Job $currJob
    Start-Sleep -Milliseconds $sleepIntervalMs  # sleep a little
  }

  # Determine the first / newest log.
  $newLog = Get-ChildItem -LiteralPath $dir -Filter $logFilePattern | Sort-Object CreationTimeUtc -Descending | Select-Object -First 1
  if ($newLog.FullName -ne $currLog.FullName) { # new log file found.

    Write-Verbose "(New) log file found: $newLog"

    if ($currJob) {
        Write-Verbose "Terminating background job for previous log ($currLog)."
        Remove-Job -Job $currJob -Force
        # When a *new* log was just started, we show *all* lines (and keep listening for more).
        $tailArg = @{} 
    } else {
        # When we first start monitoring, we start with the *last 10* lines
        # of the current log (and keep listening for more).
        $tailArg = @{ Tail = 10 } # On first
    }

    $currLog = $newLog

    Write-Verbose "Starting background job for $currLog..."
    # Start the background job for the new log.
    $currJob = Start-Job { Get-Content -Wait @using:tailArg -LiteralPath $using:newLog.FullName }

  }

}
Write-Host -ForegroundColor Green "Terminated."

推荐阅读