the not name exist español does current cs0103 context powershell powershell-v3.0

powershell - not - django pdf español



Get-Content-wait no funciona como se describe en la documentación (6)

Me di cuenta de que cuando Get-Content path/to/logfile -Wait , el resultado no se actualiza cada segundo como lo explica la documentación. Si voy en el Explorador de Windows a la carpeta donde está el archivo de registro y actualizo la carpeta, Get-Content generará los últimos cambios en el archivo de registro.

Si pruebo tail -f con cygwin en el mismo archivo de registro (no al mismo tiempo que cuando intento get-content ), se ve como se espera, refrescando en tiempo real sin que tenga que hacer nada.

¿Alguien tiene una idea de por qué sucede esto?


¿Puedes decirnos cómo reproducir eso?

Puedo comenzar este script en una sesión de PS:

get-content c:/testfiles/test1.txt -wait

y esto en otra sesión:

while (1){ get-date | add-content c:/tesetfiles/test1.txt Start-Sleep -Milliseconds 500 }

Y veo las nuevas entradas escritas en la primera sesión.


Me encontré con el mismo problema al tratar de ver WindowsUpdate.log en tiempo real. Aunque no es ideal, el siguiente código me permitió monitorear el progreso. -Espera no funcionó debido a las mismas limitaciones de escritura de archivos discutidas anteriormente.

Muestra las últimas 10 líneas, duerme durante 10 segundos, borra la pantalla y luego muestra las últimas 10 nuevamente. CTRL + C para detener la transmisión.

while(1){ Get-Content C:/Windows/WindowsUpdate.log -tail 10 Start-Sleep -Seconds 10 Clear }


Parece que Powershell está monitoreando la propiedad Last Modified del archivo. El problema es que "por motivos de rendimiento", los metadatos NTFS que contienen esta propiedad no se actualizan automáticamente, excepto bajo ciertas circunstancias.

Una circunstancia es cuando se cierra el identificador del archivo (de ahí las observaciones de @Duncan ). Otro es cuando la información del archivo se consulta directamente, de ahí el comportamiento de actualización Explorer mencionado en la pregunta.

Puede observar la correlación haciendo que Powershell supervise un registro con Get-Content -Wait y tenga abierto el Explorador en la carpeta en la vista de detalles con la columna Last Modified visible. Observe que Last Modified no se actualiza automáticamente a medida que se modifica el archivo.

Ahora obtenga las propiedades del archivo en otra ventana. Por ejemplo, en el símbolo del sistema, type el archivo. O abra otra ventana del Explorador en la misma carpeta, haga clic con el botón derecho en el archivo y obtenga sus propiedades (para mí, basta con hacer clic con el botón derecho). Tan pronto como lo haga, la primera ventana del Explorador actualizará automáticamente la columna Last Modified y Powershell notará la actualización y se pondrá al día con el registro. En Powershell, tocar la propiedad LastWriteTime es suficiente:

(Get-Item file.log).LastWriteTime = (Get-Item file.log).LastWriteTime

o

(Get-Item file.log).LastWriteTime = Get-Date

Entonces esto ahora me funciona:

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


Parece que get-content solo funciona si pasa por la API de Windows y las versiones de anexar a un archivo son diferentes.

program.exe > output.txt

Y entonces

get-content output.txt -wait

No se actualizará Pero

program.exe | add-content output.txt

trabajará con.

get-content output.txt -wait

Así que supongo que depende de cómo la aplicación genera resultados.


Puedo asegurarle que Get-Content -Wait se actualiza cada segundo y muestra los cambios cuando el archivo cambia en el disco. No estoy seguro de qué tail -f está haciendo de manera diferente, pero según su descripción, estoy casi seguro de que este problema no está en PowerShell, sino en el almacenamiento en caché de escritura. No puedo descartar la posibilidad de que log4net esté haciendo el almacenamiento en caché, pero sospecho fuertemente que el almacenamiento en caché a nivel del sistema operativo es el culpable, por dos razones:

  1. La documentación para log4j / log4net dice que vacía el búfer después de cada operación de adición de forma predeterminada, y supongo que si lo hubiera configurado explícitamente para no descargar después de cada anexión, lo sabría.
  2. Sé con certeza que actualizar Windows Explorer desencadena una descarga de búfer de escritura si han cambiado los archivos en el directorio. Esto se debe a que realmente lee el contenido del archivo, no solo los metadatos, para proporcionar información extendida, como miniaturas y vistas previas, y la operación de lectura hace que el buffer de escritura se vacíe. Por lo tanto, si ve las actualizaciones demoradas cada vez que actualiza el directorio del archivo de registro en el Explorador de Windows, eso apunta fuertemente en esta dirección.

Intente esto: abra el Administrador de dispositivos, expanda el nodo Discos de disco , abra las Propiedades del disco en el que está almacenado el archivo de registro, cambie a la pestaña Políticas y desmarque Habilitar caché de escritura en el dispositivo . Creo que encontrará que Get-Content -Wait ahora le mostrará los cambios a medida que ocurren.

En cuanto a por qué tail -f está mostrando los cambios de inmediato tal como están, solo puedo especular. Tal vez lo esté usando para monitorear un archivo de registro en una unidad diferente, o tal vez Cygwin solicite descargas frecuentes mientras ejecuta tail -f , para abordar este mismo problema.

ACTUALIZAR:

Duncan comentó a continuación que es un problema con PowerShell, y publicó una respuesta sosteniendo que Get-Content -Wait no genera nuevos resultados hasta que se cierra el archivo, al contrario de la documentación.

Sin embargo, en base a la información ya establecida y las pruebas adicionales, he confirmado de manera concluyente que no espera a que se cierre el archivo, sino que genera nuevos datos agregados al archivo tan pronto como se escribe en el disco, y que el problema es ver es casi definitivamente debido a escribir buffering.

Para demostrar esto, permita que los hechos se presenten a un mundo sincero:

  • Creé una hoja de cálculo de Excel y ejecuté Get-Content -Wait contra el archivo .xlsx. Cuando ingresé datos nuevos en la hoja de cálculo, el Get-Content -Wait no produjo nuevos resultados, lo cual se espera mientras la información nueva está solo en la memoria RAM y no en el disco. Sin embargo, cada vez que guardaba la hoja de cálculo después de agregar datos, se producía una nueva salida inmediatamente.

    Excel no cierra el archivo cuando lo guarda. El archivo permanece abierto hasta que cierre la ventana desde Excel o salga de Excel. Puede verificar esto al intentar eliminar, cambiar el nombre o modificar el archivo .xlsx una vez que lo haya guardado, mientras la ventana aún esté abierta en Excel.

  • El OP indicó que obtiene un nuevo resultado cuando actualiza la carpeta en el Explorador de Windows. Actualizar el listado de carpetas no cierra el archivo. Vacía el búfer de escritura si alguno de los archivos ha cambiado. Esto se debe a que tiene que leer los atributos del archivo y esta operación vacía el búfer de escritura. Trataré de encontrar algunas referencias para esto, pero como señalé anteriormente, sé con certeza que esto es cierto.

  • Verifiqué este comportamiento ejecutando la siguiente versión modificada de la prueba de Duncan, que se ejecuta para 1,000 iteraciones en lugar de 50, y muestra el progreso en la consola para que pueda rastrear exactamente cómo se relaciona el resultado en su ventana Get-Content -Wait con los datos que la tubería ha agregado al archivo:

    1..1000 | %{"${_}: Write $(Get-Date -Format "hh:mm:ss")"; Write-Host -NoNewline "$_..."; Start-Sleep 1} > ./gcwtest.txt

    Mientras esto se estaba ejecutando, ejecuté Get-Content -Wait ./gcwtest.txt en otra ventana y abrí el directorio en Windows Explorer. Descubrí que si actualizo, se produce más salida cada vez que cambia el tamaño del archivo en KB, y en ocasiones, aunque no siempre, incluso si no ha cambiado nada visible. (Más sobre las implicaciones de esa inconsistencia más adelante ...)

  • Utilizando la misma prueba, abrí una tercera ventana de PowerShell y observé que todas las siguientes activan una actualización inmediata en la lista Get-Content -Wait :

    • Get-Content ./gcwtest.txt los contenidos del archivo con Get-Content ./gcwtest.txt antiguo simple Get-Content ./gcwtest.txt

    • Leyendo cualquiera de los atributos del archivo. Sin embargo, para los atributos que no cambian, solo la primera lectura activa una actualización.

      Por ejemplo, (gi ./gcwtest.txt).lastwritetime desencadena más salida varias veces. Por otro lado, (gi ./gcwtest.txt).mode o (gi ./gcwtest.txt).directory desencadenan más salida la primera vez cada uno, pero no si los repite. También tenga en cuenta lo siguiente:

      » Este comportamiento no es 100% consistente. A veces, leer Modo o Directorio no desencadena más salida la primera vez, pero lo hace si repite la operación. Todas las repeticiones posteriores a la primera que activa la salida actualizada no tienen efecto.

      » Si repite la prueba, leer los atributos que son iguales no desencadena la salida, a menos que elimine el archivo .txt antes de volver a ejecutar la interconexión. De hecho, a veces incluso (gi ./gcwtest.txt).lastwritetime no desencadena más resultados si repite la prueba sin eliminar gcwtest.txt .

      » Si emite (gi ./gcwtest.txt).lastwritetime varias veces en un segundo, solo el primero activa la salida, es decir, solo cuando el resultado ha cambiado.

    • Abrir el archivo en un editor de texto. Si utiliza un editor que mantiene abierto el identificador del archivo (el bloc de notas no), verá que cerrar el archivo sin guardarlo no provoca Get-Content -Wait a generar las líneas agregadas por el conducto desde que abrió el archivo en el editor.

    • Tabulador: completando el nombre del archivo

  • Después de probar alguna de las pruebas anteriores varias veces, muchos encuentran que Get-Content -Wait genera más líneas periódicamente durante el resto de la ejecución de la interconexión, incluso si no hace nada. No una línea a la vez, sino en lotes.

  • La incoherencia en el comportamiento en sí apunta al enjuague del buffer, que ocurre de acuerdo con criterios variables que son difíciles de predecir, en oposición al cierre, que ocurre bajo circunstancias claras y consistentes.

Conclusión: Get-Content -Wait funciona exactamente como se anuncia. El nuevo contenido se muestra tan pronto como se escribe físicamente en el archivo en el disco * .

Cabe señalar que mi sugerencia de desactivar el almacenamiento en caché de escritura en el disco no fue para la prueba anterior, es decir, no dio como resultado `Get-Content -Wait que muestra nuevas líneas tan pronto como se agregan al archivo de texto por la tubería , por lo que quizás el almacenamiento en búfer responsable de la latencia de salida se produzca en un sistema de archivos o sistema operativo en lugar de en la memoria caché de escritura del disco. Sin embargo, escribir buffering es claramente la explicación del comportamiento observado en la pregunta del OP.

* No voy a entrar en esto en detalle, ya que está fuera del alcance de la pregunta, pero Get-Content -Wait se comporta de manera extraña si agrega contenido al archivo no al final. Muestra datos del final del archivo de igual tamaño a la cantidad de datos agregados. Los datos recién visualizados generalmente repiten datos que se mostraron previamente, y pueden o no incluir cualquiera de los datos nuevos, dependiendo de si el tamaño de los nuevos datos excede el tamaño de los datos que le siguen.


Editar: Bernhard König informa en los comentarios que esto finalmente se ha corregido en Powershell 5.

Estás en lo cierto. La opción -Wait en Get-Content espera hasta que se haya cerrado el archivo antes de que lea más contenido. Es posible demostrar esto en Powershell, pero puede ser complicado acertar como loops como:

while (1){ get-date | add-content c:/tesetfiles/test1.txt Start-Sleep -Milliseconds 500 }

abrirá y cerrará el archivo de salida cada vez que pasa el ciclo.

Para demostrar el problema, abra dos ventanas de Powershell (o dos pestañas en el ISE). En uno ingrese este comando:

PS C:/> 1..30 | % { "${_}: Write $(Get-Date -Format "hh:mm:ss")"; start-sleep 1 } >C:/temp/t.txt

Eso se ejecutará durante 30 segundos escribiendo 1 línea en el archivo cada segundo, pero no se cierra y abre el archivo cada vez.

En la otra ventana use Get-Content para leer el archivo:

get-content c:/temp/t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" }

Con la opción -Wait , necesita usar Ctrl + C para detener el comando, así que ejecutar ese comando 3 veces esperando unos segundos después de cada uno de los primeros dos y una espera más larga después del tercero me dio esta salida:

PS C:/> get-content c:/temp/t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" } 8: Write 12:15:09 read at 12:15:09 PS C:/> get-content c:/temp/t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" } 13: Write 12:15:14 read at 12:15:15 PS C:/> get-content c:/temp/t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" } 19: Write 12:15:20 read at 12:15:20 20: Write 12:15:21 read at 12:15:32 21: Write 12:15:22 read at 12:15:32 22: Write 12:15:23 read at 12:15:32 23: Write 12:15:24 read at 12:15:32 24: Write 12:15:25 read at 12:15:32 25: Write 12:15:26 read at 12:15:32 26: Write 12:15:27 read at 12:15:32 27: Write 12:15:28 read at 12:15:32 28: Write 12:15:29 read at 12:15:32 29: Write 12:15:30 read at 12:15:32 30: Write 12:15:31 read at 12:15:32

De esto puedo ver claramente:

  1. Cada vez que se ejecuta el comando, se obtiene la última línea escrita en el archivo. es decir, no hay ningún problema con el almacenamiento en caché y no hay búferes que necesiten enjuagarse.
  2. Solo se lee una línea y luego no aparece ninguna salida hasta que se completa el comando que se ejecuta en la otra ventana.
  3. Una vez que completa, todas las líneas pendientes aparecen juntas. Esto debe haber sido desencadenado por el programa fuente que cierra el archivo.

También cuando repetí el ejercicio con el comando Get-Content ejecutándose en otras dos ventanas, una ventana leyó la línea 3 y luego esperó, la otra ventana leyó la línea 6, por lo que la línea definitivamente se está escribiendo en el archivo.

Parece bastante concluyente que la opción -Wait está esperando un evento de cierre de archivo, sin esperar el anunciado 1 segundo. La documentación es incorrecta.

Editar: Debo agregar, como Adi Inbar parece insistir en que estoy equivocado, que los ejemplos que di aquí usan Powershell solo como parece más apropiado para una discusión de Powershell. También verifiqué usando Python que el comportamiento es exactamente como lo describí:

El contenido escrito en un archivo es legible mediante un nuevo comando Get-Content -Wait siempre que la aplicación haya descargado su búfer.

Una instancia de Powershell que utiliza Get-Content -Wait no mostrará contenido nuevo en el archivo que se está escribiendo, aunque otra instancia de Powershell, iniciada más tarde, vea los datos posteriores. Esto prueba de manera concluyente que Powershell y Get-Content -Wait acceder a los datos. Get-Content -Wait no sondear a intervalos de 1 segundo, pero esperando algún evento desencadenante antes de buscar los datos.

El tamaño del archivo según lo informado por el dir está actualizando mientras se están agregando líneas, por lo que no es un caso de Powershell a la espera de que se actualice el tamaño de la entrada del directorio.

Cuando el proceso de escritura del archivo lo cierra, Get-Content -Wait muestra el nuevo contenido casi al instante. Si estuviera esperando hasta que los datos fueran descargados en el disco, habría una demora hasta que Windows vació su caché de disco.

@AdiInbar, me temo que no entiende lo que Excel hace cuando guarda un archivo. Eche un vistazo más de cerca. Si está editando test.xlsx , también hay un archivo oculto ~test.xlsx en la misma carpeta. Utilice dir ~test.xlsx -hidden | select CreationTime dir ~test.xlsx -hidden | select CreationTime para ver cuándo fue creado. Guarde su archivo y ahora test.xlsx tendrá el tiempo de creación desde ~test.xlsx . En otras palabras, al guardar en Excel se guarda en el archivo ~ , luego se borra el original, se renombra el archivo ~ al nombre original y se crea un nuevo archivo ~ . Hay una gran cantidad de apertura y cierre pasando allí.

Antes de guardarlo, tiene abierto el archivo que está mirando y después de que ese archivo está abierto, pero es un archivo diferente. Creo que Excel es un escenario demasiado complejo para decir exactamente qué hace que Get-Content muestre contenido nuevo, pero estoy seguro de que lo malinterpretó.