いくつかの例を確認した後、カスタムのテールのような関数を実装しようとすると、次のコードにたどり着きました。これは非常にうまく機能します(ファイル全体をロードして X 終了行を読み取るのではなく、ネットワーク パスに対して機能します ...)
私が抱えている問題は、現在の位置の10行前にあるストリームポインタを移動する方法がないことです?
回避策として、ポインターを現在の位置の1024バイト前に移動しますが、これが実際に関係している行数はわかりません。
$sr=New-Object System.IO.StreamReader($fs)
$lastPosition=$sr.BaseStream.Length # final position of the file
$currentPosition=$lastPosition - 1024
誰でも私を正しい方向に向けることができますか?
完全なコードは次のとおりです。
function tail{
[cmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$filename, # path
[int]$n=10, # number of lines to output
[switch]$continous, # continue to monitor for changes ?
[switch]$hilight # hilight lines containing keywords ?
)
# Initialising stuff
$hilightError=@("erreur","error","fatal","critic")
$hilightWarning=@("attention","warning","notice")
$errorColor="red"
$warningColor="darkyellow"
if ( (test-Path $filename) -eq $false){
write-Error "Cant read this file !"
exit
}
function tailFile($ptr){
# return each line from the pointer position to the end of file
$sr.BaseStream.Seek($ptr,"Begin")
$line = $sr.ReadLine()
while ( $line -ne $null){
$e=$w=$false
if( $hilight){
$hilightError | %{ $e = $e -or ($line -match $_) } # find error keywords ?
if( $e) {wh $line -ForegroundColor $errorColor }
else{
$hilightWarning | %{ $w = $w -or ($line -match $_ ) } # find warning keywords ?
if($w){ wh $line -ForegroundColor $warningColor }
else{ wh $line}
}
}
else{ #no hilight
wh $line
}
$line = $sr.ReadLine()
}
}
# Main
$fs=New-Object System.IO.FileStream ($filename,"OpenOrCreate", "Read", "ReadWrite",8,"None") # use ReadWrite sharing permission to not lock the file
$sr=New-Object System.IO.StreamReader($fs)
$lastPosition=$sr.BaseStream.Length # final position of the file
$currentPosition=$lastPosition - 1024 # take some more bytes (to get the last lines)
tailfile $currentPosition
if($continous){
while(1){
start-Sleep -s 1
# have the file changed ?
if ($sr.BaseStream.Length -eq $lastPosition){
write-verbose "no change..."
continue
}
else {
tailfile $lastPosition
$lastPosition = $sr.BaseStream.Position
write-Verbose "new position $lastPosition"
}
}
}
$sr.close()
}