web-dev-qa-db-fra.com

Get-Content -wait ne fonctionne pas comme décrit dans la documentation

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?

26
julio.g

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
11
CupawnTae

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. 

2
mjolinor

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 
    }
1
Justin Kittle

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.

1
Milhous