J'ai remarqué que lorsque Get-Content path/to/logfile -Wait
, le résultat n'est pas actualisé à chaque seconde, comme l'explique la documentation. Si je vais dans l'explorateur Windows dans le dossier où se trouve le fichier journal et que le message est actualisé, Get-Content
affichera les dernières modifications apportées au fichier journal.
Si j'essaie tail -f
avec cygwin sur le même fichier journal (pas au même moment que lorsque j'essaie get-content
), alors tout se passe comme prévu, rafraîchissant en temps réel sans que je ne fasse rien.
Quelqu'un at-il une idée pourquoi cela se produit?
Il semble que Powershell surveille la propriété Last Modified
du fichier. Le problème est que "pour des raisons de performances" les métadonnées NTFS contenant cette propriété sont non automatiquement mises à jour sauf dans certaines circonstances.
Une circonstance est lorsque le descripteur de fichier est fermé (d'où observations de @ Duncan ). Une autre est lorsque les informations du fichier sont interrogées directement, d'où le comportement d'actualisation de l'explorateur mentionné dans la question.
Vous pouvez observer la corrélation en faisant en sorte que Powershell surveille un journal avec Get-Content -Wait
et en ouvrant Explorer dans le dossier de la vue détaillée avec la colonne Last Modified
visible. Notez que Last Modified
ne se met pas à jour automatiquement lors de la modification du fichier.
Maintenant, récupérez les propriétés du fichier dans une autre fenêtre. Par exemple. à l'invite de commande, type
le fichier. Ou ouvrez une autre fenêtre de l'Explorateur dans le même dossier, cliquez avec le bouton droit de la souris sur le fichier et obtenez ses propriétés (pour moi, un clic droit suffit). Dès que vous faites cela, la première fenêtre de l'Explorateur mettra automatiquement à jour la colonne Last Modified
et Powershell remarquera la mise à jour et rattrapera le journal. Dans Powershell, il suffit de toucher la propriété LastWriteTime
:
(Get-Item file.log).LastWriteTime = (Get-Item file.log).LastWriteTime
ou
(Get-Item file.log).LastWriteTime = Get-Date
Donc, cela fonctionne maintenant pour moi:
Start-Job {
$f=Get-Item full\path\to\log
while (1) {
$f.LastWriteTime = Get-Date
Start-Sleep -Seconds 10
}
}
Get-Content path\to\log -Wait
Pouvez-vous nous dire comment reproduire cela?
Je peux démarrer ce script sur une session PS:
get-content c:\testfiles\test1.txt -wait
et ceci dans une autre session:
while (1){
get-date | add-content c:\tesetfiles\test1.txt
Start-Sleep -Milliseconds 500
}
Et je vois les nouvelles entrées en cours d'écriture dans la première session.
J'ai rencontré le même problème en essayant de regarder WindowsUpdate.log en temps réel. Bien que cela ne soit pas idéal, le code ci-dessous m'a permis de surveiller les progrès. -L'attente n'a pas fonctionné en raison des mêmes limitations d'écriture de fichier que celles décrites ci-dessus.
Affiche les 10 dernières lignes, dort pendant 10 secondes, efface l'écran, puis affiche à nouveau les 10 dernières. CTRL + C pour arrêter le flux.
while(1){
Get-Content C:\Windows\WindowsUpdate.log -tail 10
Start-Sleep -Seconds 10
Clear
}
Il semble que get-content ne fonctionne que s’il passe par l’API Windows et que les versions de l’ajout à un fichier sont différentes.
program.exe > output.txt
Et alors
get-content output.txt -wait
Ne mettra pas à jour. Mais
program.exe | add-content output.txt
travaillera avec.
get-content output.txt -wait
Donc, je suppose que cela dépend de la manière dont l'application produit.