Perché il reindirizzamento dell'output sed sullo stesso file di input non risponde alla mia macchina?


13

Stavo cercando seddi sostituire alcune parole chiave in un file di grandi dimensioni (100 MB). Non ero a conoscenza -idell'opzione (sul posto), quindi il mio primo tentativo è stato di reindirizzare in questo modo:

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

quello che è successo dopo è stato che il mio PC si è fermato, quasi senza input da tastiera. Ho provato una console diversa Ctrl+ Alt+ F1ma dopo aver inserito lentamente il nome utente, si è anche fermato. Senza tastiera, la mia unica opzione era ripristinare l'hardware della macchina. Dopo aver effettuato l'accesso, ho visto che file.log era di circa 8 GB.

Vorrei davvero capire perché l'esecuzione di quel comando è stata in grado di rendere il sistema così non rispondente e se esistono meccanismi a livello di sistema per attivare avvisi e terminare il processo offensivo?


7
È una macchina single core? Sembra molto strano che questo avrebbe dovuto mettere in ginocchio un computer moderno. Riempito il tuo disco, sì. Hai esaurito il 100% di uno dei tuoi core, sì. Ma un incidente completo?
terdon,

C'è qualcosa di strano in quel file? se questo non è un problema, potresti pubblicarne i contenuti su pastebin?
Sergiy Kolodyazhnyy,

Inoltre, qual è la quantità della tua memoria? Potresti fornirci un output di free -h ?
Sergiy Kolodyazhnyy il

Perché utilizzare un editor di stream in primo luogo quando si desidera modificare un file? ex -sc '%s/original/edited/ge|x' file.logdovrebbe fare quello che vuoi in modo idiomatico UNIX senza gli sed -ieffetti collaterali.
David Ongaro,

Nota che anche se lo stai facendo correttamente (con uno qualsiasi dei metodi forniti dalle persone), può essere rischioso fare questo tipo di cose a un file di registro appartenente a un processo attivo.
Casuale 832

Risposte:


10

Come è già stato detto, >>accoda il file, quindi il tuo sedcomando siederà lì leggendo le righe che ha appena emesso, e poi emettendole ancora un po '. Se si voleva sostituire il file sul posto, >ancora non avrebbe funzionato, ma siete a conoscenza di sed's -iopzione, che è sicuramente quello che si desidera.

Se, tuttavia, sei assolutamente sicuro di voler aggiungere a un file che stai leggendo come stream e vuoi fare solo un passaggio, prendi in considerazione l'uso spongedal moreutilspacchetto;

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

spongelegge da stdin in memoria fino a EOF, quindi scarica tutto il suo contenuto su stdout, quindi sedcolpirà la fine del file, interromperà la lettura, lo chiuderà e quindi sponge inizierà ad aggiungerlo.


2
spongeè un bel programma di utilità di conoscere, ma sedha già -iun'opzione: -i[SUFFIX], --in-place[=SUFFIX], edit files in place (makes backup if SUFFIX supplied).
Joshua Taylor,

@JoshuaTaylor, stava usando OP >>, che aggiunge invece >che sostituisce. Certo, OP aveva menzionato -iin modo specifico nel post e sembra un caso d'uso molto più comune di questo, ma ho pensato che valesse la pena sottolineare che l'operazione specifica che OP aveva pubblicato era possibile senza troppa fatica, se sei davvero certo è quello che vuoi fare.
ymbirtt

1
L'ho menzionato qui perché era la chiave nella risposta accettata . Detto questo, sono sinceramente felice di conoscere la spugna ; è un nuovo strumento per la mia cassetta degli attrezzi, e degno di un voto solo per quello.
Joshua Taylor,

1
Ah! Vedo. Modificherò la mia risposta per renderlo un po 'più chiaro. Inoltre, se ti è piaciuto sponge, dai un'occhiata vipe. moreutilsè solo un pacchetto magico pieno di cose che non sapevi di aver mai bisogno
ymbirtt

18

Il tuo sedcomando stava provando a leggere il file a cui stava aggiungendo. Non raggiungerà mai l'End-Of-File, ma ci vorrà molto tempo per provare la CPU. Ecco perché è stato inventato ^ C (interrompi processo corrente).


Non credo che ^ C sia stata un'opzione lì ... è andata a HALT, cioè nessun cursore lampeggiante, bloccato!
EKons

18

L'aggiunta al file da cui hai letto non è in alcun caso una buona idea, in quanto finirai con un file in continua crescita. Se vuoi davvero riscrivere nel file dovresti usare il -iflag:

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

o se si desidera che crei un backup prima di apportare modifiche, è possibile aggiungere un suffisso di file al -iflag:

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

Ciò creerebbe un file chiamato file.log.bake quindi facendo delle modifiche, cosa hai fatto lì provando ad aggiungere al file che stai leggendo chiamiamo nel programmatore un gergo di dati, in cui diversi processi corrono per la stessa fonte di dati sia in input che in output . Questo è anche il motivo per cui la tua macchina si è fermata.


1
Sono sorpreso che questa sia la risposta accettata, perché non risponde nemmeno alla domanda di 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 Per questo motivo mi sono fermato, ma per la seconda parte hai ragione. Non mi sono rivolto a questo perché non conosco una risposta a questo. Abbiamo testato ampiamente il comando dopo una discussione in chat e abbiamo ottenuto risultati totalmente diversi su macchine e sistemi operativi diversi. Esempio: su una macchina con arch lascia che il file cresca per sempre, ma non rende la macchina non rispondente. Sulla mia macchina Ubuntu ottenevo lo stesso risultato dell'interrogante senza la possibilità di interrompere il processo. Una seconda macchina che testava lo stesso in una macchina virtuale Ubuntu si è fermata.
Videonauth,

Un straceintero processo dall'altra parte non ha riprodotto il risultato e questo sulla mia macchina e sulla macchina di un altro utente. Sicuramente ci sono meccanismi con cui puoi uccidere le applicazioni che non rispondono, ma se la tua macchina non risponde, rimani solo con un'opzione, ripristinandola. Sto ancora testando questo e prima di non capire appieno ciò che sta causando il comportamento descritto, non sono in grado di affrontare questa parte della domanda.
Videonauth,

Probabilmente è una differenza nelle configurazioni del kernel, come un diverso scheduler che dà la priorità a IO, o differenze nel driver del disco / filesystem tra i sistemi. È bello vedere le indagini che avete fatto, questa è una buona informazione.
Steve,

Se sei interessato a un altro punto dati; Ho provato questo su una macchina CentOS con un file abbastanza piccolo, e ha fatto esattamente la stessa cosa della mia soluzione di spugna di seguito. Immagino che per un file di dimensioni ridotte sedmemorizzerà l'intera cosa in memoria e poi la chiuderà, invece di tenere la maniglia. Con un file di ~ 100 MB, come in OP, è cresciuto indefinitamente ma non ha bloccato la macchina.
ymbirtt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.