¿Por qué la redirección de la salida sed al mismo archivo de entrada hace que mi máquina no responda?

13

Estaba tratando sedde reemplazar algunas palabras clave en un archivo grande (100 MB). No tenía conocimiento de la -iopción (in situ), así que mi primer intento fue redirigir así:

sed 's/original/edited/g' file.log >> file.log

Lo que sucedió después de eso fue que mi PC se detuvo, casi sin entrada de teclado. Probé una consola diferente Ctrl+ Alt+ F1pero después de ingresar lentamente el nombre de usuario, también se detuvo. Sin teclado, mi única opción era restablecer el hardware de la máquina. Después de iniciar sesión, vi que file.log tenía unos 8 GB.

Realmente me gustaría entender por qué la ejecución de ese comando pudo hacer que el sistema no respondiera tanto, y si existen mecanismos a nivel del sistema para activar alertas y matar el proceso ofensivo.

cesarpachon
fuente
77
¿Es esta una máquina de núcleo único? Parece muy extraño que esto debería haber puesto de rodillas a una computadora moderna. Llena tu disco, sí. Usó el 100% de uno de sus núcleos, sí. Pero un choque completo?
terdon
¿Hay algo peculiar en ese archivo? Si esto no es un problema, ¿podría publicar su contenido en pastebin?
Sergiy Kolodyazhnyy
Además, ¿cuál es la cantidad de tu memoria? ¿Nos puede proporcionar con una producción de free -h ?
Sergiy Kolodyazhnyy
¿Por qué usar un editor de flujo en primer lugar cuando quieres cambiar un archivo? ex -sc '%s/original/edited/ge|x' file.logdebe hacer lo que quiera de forma idiomática UNIX sin los sed -iefectos secundarios.
David Ongaro
Tenga en cuenta que incluso si lo está haciendo correctamente (por cualquiera de los métodos que proporciona la gente), puede ser peligroso hacer este tipo de cosas en un archivo de registro que pertenece a un proceso activo.
Random832

Respuestas:

10

Como ya se ha dicho, se >>agrega al archivo, por lo que su sedcomando se quedará allí leyendo las líneas que acaba de emitir y luego emitiéndolas un poco más. Si quisiera reemplazar su archivo en el lugar, >todavía no funcionaría, pero conoce sedla -iopción, que definitivamente es la que desea.

Sin embargo, si está absolutamente seguro de que desea agregar a un archivo que está leyendo como una secuencia, y solo desea hacer una pasada, considere usarlo spongedesde el moreutilspaquete;

sed 's/original/edited/g' file.log | sponge >> file.log

spongelee desde stdin en la memoria hasta EOF, luego volca todo su contenido en stdout, por sedlo que llegará al final del archivo, dejará de leerlo, lo cerrará y luego la esponja comenzará a agregarse a él.

ymbirtt
fuente
2
spongees una buena utilidad para conocer, pero sedya tiene una -iopción: -i[SUFFIX], --in-place[=SUFFIX], edit files in place (makes backup if SUFFIX supplied).
Joshua Taylor
@JoshuaTaylor, OP estaba usando >>, que agrega, en lugar de >, que reemplaza. De acuerdo, OP había mencionado específicamente -ien la publicación y parece un caso de uso mucho más común que este, pero pensé que valía la pena señalar que la operación específica que OP había publicado era posible sin demasiadas fallas, si realmente Seguro que es lo que quieres hacer.
ymbirtt
1
Lo mencioné aquí porque era la clave en la respuesta aceptada . Dicho esto, estoy realmente feliz de aprender acerca de la esponja ; es una nueva herramienta para mi caja de herramientas, y merece un voto positivo solo por eso.
Joshua Taylor
1
Ah! Veo. Ajustaré mi respuesta para que quede un poco más claro. Además, si disfrutaste sponge, échale un vistazo vipe. moreutilses sólo un paquete mágico lleno de cosas que no sabías que necesitabas
ymbirtt
18

Su sedcomando intentaba leer el archivo al que se estaba agregando. Nunca llegará al final del archivo, pero consumirá mucho tiempo de CPU en el intento. Es por eso que se inventó ^ C (interrumpir el proceso actual).

Waltinator
fuente
No creo que ^ C fuera una opción allí ... fue a un HALT, es decir, sin cursor parpadeante, atascado!
EKons
18

Volver a agregar al archivo que leyó no es en ningún caso una buena idea, ya que terminará con un archivo cada vez mayor. Si realmente desea volver a escribir en el archivo, debe usar la -ibandera:

sed -i 's/original/edited/g' file.log

o si desea que cree una copia de seguridad antes de hacer cambios, puede agregar un sufijo de archivo al -iindicador:

sed -i.bak 's/original/edited/g' file.log

Esto crearía un archivo llamado file.log.baky luego haciendo cambios, lo que hiciste al intentar agregar al archivo que estás leyendo llamamos en la jerga del programador una carrera de datos, donde diferentes procesos compiten por la misma fuente de datos ya sea de entrada o salida . Esta es también la razón por la cual su máquina se detuvo.

Videonauth
fuente
1
Me sorprende que esta sea la respuesta aceptada, porque ni siquiera aborda la pregunta de OP"I really would like to understand why the execution of that command was able to make the system so unresponsive, and if mechanisms exist at the system level to trigger alerts and kill the offending process?"
Steve
@Steve Por qué se detuvo, me dirigí, pero en la segunda parte tienes razón. No abordé eso porque no sé una respuesta a esto. Probamos el comando después de una discusión de chat ampliamente y obtuvimos resultados totalmente diferentes en diferentes máquinas y sistemas operativos. Ejemplo: en una máquina con arco solo permite que el archivo crezca para siempre, pero no hace que la máquina no responda. En mi máquina Ubuntu estaba obteniendo el mismo resultado que el interrogador sin una oportunidad de matar el proceso. Una segunda máquina que probó lo mismo en una máquina virtual Ubuntu se detuvo.
Videonauth
Una parte stracedel proceso completo en el otro lado no reprodujo el resultado y esto en mi máquina y en la máquina de otro usuario. Claro que hay un mecanismo con el que puede eliminar aplicaciones que no responden, pero si su máquina deja de responder, solo le queda una opción, reiniciarla. Todavía estoy probando esto y antes de no entender completamente qué está causando el comportamiento descrito, no puedo abordar esta parte de la pregunta.
Videonauth
Probablemente sea una diferencia en las configuraciones del kernel, como un planificador diferente que priorice IO, o diferencias en el controlador de disco / sistema de archivos entre los sistemas. Es bueno ver la investigación que hicieron, es buena información.
Steve
Si está interesado en otro punto de datos; Intenté esto en una máquina CentOS con un archivo bastante pequeño, e hizo exactamente lo mismo que mi solución de esponja a continuación. Me imagino que para un archivo pequeño sedalmacenará todo en la memoria y luego lo cerrará, en lugar de mantener el control. Con un archivo de ~ 100 MB, como en OP, creció indefinidamente pero no bloqueó la máquina.
ymbirtt