gpt4 book ai didi

用于监视日志并将进度输出到另一个的 PowerShell 脚本

转载 作者:行者123 更新时间:2023-12-04 07:14:40 25 4
gpt4 key购买 nike

我有一个 PowerShell 脚本可以将我们的 Windows 10 计算机升级到更新的功能更新。该脚本还会在某些步骤进行时记录它们,以便我们可以跟踪它们。但是,实际的升级步骤需要几个小时,并且(目前)在完成之前无法看到它的进展。这是我到目前为止所拥有的:

Get-Content -Path "C:\$WINDOWS.~BT\Sources\Panther\setupact.log" -Tail 0 -Wait | Where {$_ -Match "Mapped\ Global\ progress:\ \[10%]"}
Add-Content -Path "\\SERVER1\Logs\Upgrade.log" -Value "Upgrade stage is at 10% progress"
Get-Content -Path "C:\$WINDOWS.~BT\Sources\Panther\setupact.log" -Tail 0 -Wait | Where {$_ -Match "Mapped\ Global\ progress:\ \[20%]"}
Add-Content -Path "\\SERVER1\Logs\Upgrade.log" -Value "Upgrade stage is at 20% progress"
这是有效的,因为当脚本看到 setupact.log 中出现“Mapped Global Progress: 10%”值时更新 Upgrade.log,但问题是它停在那里并且不会检测到任何进一步的更新。我认为这是因为 -wait参数添加到 Get-Content命令。
有没有人知道一种方法(在 PowerShell 中,因为我不想使用外部程序)来监控日志,但在第一场比赛后没有遇到暂停?
谢谢。

最佳答案

这是一种您可以使用 C# 编写的 .NET 类来实现的方法。它使用一个名为 LogFileMonitor 的类,我们首先使用 Add-Type 定义它。 .
一旦类型被加载,我们就可以创建它的一个实例。它的构造函数接受将被监控的日志路径和一个 TimeSpan,用于定义我们想要检查日志中更新的频率。在下面的代码中,它被设置为每秒。
接下来我们订阅两个可用事件之一:LineAdded 或 LinesAdded。我选择使用 LinesAdded ,它每秒仅引发 1 个事件(或我们选择的任何时间跨度)并返回包含自上次检查以来添加的所有行的行列表。我们将在我们的行动中单独检查这些。
(另一个 LineAdded 将为每添加一行并提供单行引发 1 个事件。如果在最后一秒添加 10 行,则将引发 10 个事件,每行 1 行。)
订阅时,我们需要定义当我们订阅的事件被引发时我们想要执行的操作。这是我们检查匹配行并更新其他日志的地方。我决定在这里使用带有 -regex 选项的开关。当我们的任何行与我们列出的正则表达式模式之一匹配时,将执行脚本块,将内容添加到另一个日志(或我们定义的任何其他操作)

Add-Type -TypeDefinition @'
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace CustomClasses
{
public class LogFileMonitor
{
private DateTime _lastWriteTime;

private int _lineCount;
private TimeSpan _checkInterval = new TimeSpan(0, 0, 5);

public string Path { get; }
public bool Active { get; private set; } = false;

public LogFileMonitor(string path)
{
if (String.IsNullOrEmpty(path))
{
throw new ArgumentNullException("path");
}

if (!File.Exists(path))
{
throw new FileNotFoundException("Could not find file", path);
}

Path = path;
_lastWriteTime = File.GetLastWriteTime(path);
_lineCount = File.ReadAllLines(path).Length;
}

public LogFileMonitor(string path, TimeSpan interval) : this(path)
{
_checkInterval = interval;
}

public event EventHandler<LineAddedEventArgs> LineAdded;
public event EventHandler<LinesAddedEventArgs> LinesAdded;

protected virtual void OnLineAdded(LineAddedEventArgs e)
{
EventHandler<LineAddedEventArgs> handler = LineAdded;
if (handler != null)
{
handler(this, e);
}
}

protected virtual void OnLinesAdded(LinesAddedEventArgs e)
{
EventHandler<LinesAddedEventArgs> handler = LinesAdded;
if (handler != null)
{
handler(this, e);
}
}

public virtual async Task StartMonitoring()
{
if (!Active)
{
Active = true;

await Task.Run(() =>
{
do
{
DateTime currentLastWriteTime = File.GetLastWriteTime(Path);
if (_lastWriteTime != currentLastWriteTime)
{
try
{
var lines = File.ReadAllLines(Path);
_lastWriteTime = currentLastWriteTime;

if (lines.Length > _lineCount)
{
var linesAddedArgs = new LinesAddedEventArgs()
{
Lines = lines.Skip(_lineCount).ToList<string>()
};
OnLinesAdded(linesAddedArgs);

int newLineNumber = 0;
foreach (string line in lines.Skip(_lineCount))
{
var lineAddedArgs = new LineAddedEventArgs()
{
Line = line,
LineNumber = _lineCount + ++newLineNumber
};
OnLineAdded(lineAddedArgs);
}
_lineCount = lines.Length;
}
else if (lines.Length < _lineCount)
{
_lineCount = lines.Length;
}
}
catch (IOException)
{
// Log file likely being written to
}
}
Task.Delay((int)_checkInterval.TotalMilliseconds).Wait();
} while (Active);
});

Active = false;
}
else
{
throw new InvalidOperationException("Monitoring is already active. Subscribe to 'LineAdded' Event.");
}
}

public virtual void StopMonitoring()
{
Active = false;
}
}
}

public class LineAddedEventArgs : EventArgs
{
public int LineNumber { get; set; }
public string Line { get; set; }
public DateTime Time { get; } = DateTime.Now;
}

public class LinesAddedEventArgs : EventArgs
{
public List<string> Lines { get; set; }
public DateTime Time { get; } = DateTime.Now;
}
'@

$logBeingMonitored = 'C:\$WINDOWS.~BT\Sources\Panther\setupact.log'
$logProgress = '\\SERVER1\Logs\Upgrade.log'
$monitor = New-Object CustomClasses.LogFileMonitor -ArgumentList @($logBeingMonitored, [timespan]::new(0, 0, 1))

$subscriber = Register-ObjectEvent -InputObject $monitor -EventName LinesAdded -SourceIdentifier MyScript -Action {
switch -regex ($eventargs.lines) {
'Mapped\ Global\ progress:\ \[10%]' {
Add-Content -Path $logProgress -Value 'Upgrade stage is at 10% progress'
}
'Mapped\ Global\ progress:\ \[20%]' {
Add-Content -Path $logProgress -Value 'Upgrade stage is at 20% progress'
}
Default {}
}
}

$task = $monitor.StartMonitoring()

关于用于监视日志并将进度输出到另一个的 PowerShell 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68841535/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com