Pourquoi la redirection de la sortie sed vers le même fichier d'entrée fait que ma machine ne répond pas?

13

J'essayais sedde remplacer certains mots clés dans un gros fichier (100 Mo). Je n'étais pas au courant de l' -ioption (sur place), donc ma première tentative a été de rediriger comme ceci:

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

ce qui s'est passé ensuite, c'est que mon PC s'est arrêté, presque pas de saisie clavier. J'ai essayé une autre console Ctrl+ Alt+ F1mais après avoir lentement entré le nom d'utilisateur, elle s'est également arrêtée. Sans clavier, ma seule option était de réinitialiser le matériel de la machine. Après la connexion, j'ai vu que file.log était d'environ 8 Go.

Je voudrais vraiment comprendre pourquoi l'exécution de cette commande a pu rendre le système si insensible, et si des mécanismes existent au niveau du système pour déclencher des alertes et tuer le processus incriminé?

césarpachon
la source
7
S'agit-il d'une machine monocœur? Il semble très étrange que cela ait mis à genoux un ordinateur moderne. Oui, vous avez rempli votre disque. Oui, vous avez utilisé 100% de l'un de vos cœurs. Mais un crash complet?
terdon
Y a-t-il quelque chose de particulier dans ce fichier? si ce n'est pas un problème, pourriez-vous publier son contenu dans pastebin?
Sergiy Kolodyazhnyy
Quelle est également la quantité de votre mémoire? Pourriez-vous nous fournir la sortie de free -h ?
Sergiy Kolodyazhnyy
Pourquoi utiliser un éditeur de flux en premier lieu lorsque vous souhaitez modifier un fichier? ex -sc '%s/original/edited/ge|x' file.logdevrait faire ce que vous voulez d'une manière idiomatique UNIX sans les sed -ieffets secondaires.
David Ongaro
Notez que même si vous le faites correctement (par l'une des méthodes que les gens fournissent), il peut être difficile de faire ce genre de chose dans un fichier journal appartenant à un processus actif.
Random832

Réponses:

10

Comme cela a déjà été dit, >>s'ajoute au fichier, donc votre sedcommande restera là à lire les lignes qu'elle vient de sortir, puis à les sortir un peu plus. Si vous vouliez remplacer votre fichier sur place, >cela ne fonctionnerait toujours pas, mais vous connaissez sedl' -ioption de, qui est certainement celle que vous souhaitez.

Si, cependant, vous êtes absolument sûr de vouloir ajouter à un fichier que vous lisez en tant que flux, et que vous ne souhaitez effectuer qu'une seule opération, envisagez d'utiliser à spongepartir du moreutilspackage;

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

spongelit de stdin dans la mémoire jusqu'à EOF, puis vide tout son contenu sur stdout, donc sedfrappera la fin du fichier, arrêtera de le lire, le fermera, puis l'éponge commencera à s'y ajouter.

ymbirtt
la source
2
spongeest un utilitaire pratique pour savoir, mais seda déjà une -ipossibilité: -i[SUFFIX], --in-place[=SUFFIX], edit files in place (makes backup if SUFFIX supplied).
Joshua Taylor
@JoshuaTaylor, OP utilisait >>ce qui ajoute plutôt que >ce qui remplace. Certes, OP avait spécifiquement mentionné -idans le message et cela semble être un cas d'utilisation beaucoup plus courant que celui-ci, mais je pensais qu'il valait la peine de souligner que l'opération spécifique que OP avait publiée était possible sans trop de faille, si vous êtes vraiment c'est ce que vous voulez faire.
ymbirtt
1
Je l'ai mentionné ici parce que c'était la clé de la réponse acceptée . Cela dit, je suis vraiment heureux de découvrir l' éponge ; c'est un nouvel outil pour ma boîte à outils, et digne d'un vote positif juste pour cela.
Joshua Taylor
1
Ah! Je vois. Je vais modifier ma réponse pour que ce soit un peu plus clair. Aussi, si vous avez apprécié sponge, jetez un œil à vipe. moreutilsest juste un paquet magique rempli de choses dont vous n'aviez jamais
pensé avoir
18

Votre sedcommande essayait de lire le fichier auquel elle était ajoutée. Il n'atteindra jamais la fin du fichier, mais consommera beaucoup de temps processeur à essayer. C'est pourquoi ^ C (interrompre le processus en cours) a été inventé.

waltinator
la source
Je ne pense pas que ^ C était une option là-bas ... il est allé à un arrêt, c'est-à-dire pas de curseur clignotant, coincé!
EKons
18

Ajouter à nouveau le fichier que vous lisez n'est en aucun cas une bonne idée, car vous vous retrouverez avec un fichier en constante augmentation. Si vous voulez vraiment réécrire dans le fichier, vous devez utiliser l' -iindicateur:

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

ou si vous souhaitez qu'il crée une sauvegarde avant d'effectuer des modifications, vous pouvez ajouter un suffixe de fichier à l' -iindicateur:

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

Cela créerait un fichier appelé file.log.baket apporterait ensuite des modifications, ce que vous avez fait en essayant d'ajouter au fichier que vous lisez, nous appelons le programmeur argot une course aux données, où différents processus se précipitent pour la même source de données, que ce soit en entrée ou en sortie . C'est aussi pourquoi votre machine s'est arrêtée.

Videonauth
la source
1
Je suis surpris que ce soit la réponse acceptée, car elle ne répond même pas à la question d'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 Quant à savoir pourquoi il s'est arrêté, je me suis adressé, mais pour la deuxième partie, vous avez raison. Je ne l'ai pas abordé parce que je ne connais pas de réponse à cela. Nous avons testé la commande après une discussion approfondie et avons obtenu des résultats totalement différents sur différentes machines et systèmes d'exploitation. Exemple: sur une machine avec arch, cela ne fait que développer le fichier pour toujours, mais ne rend pas la machine insensible. Sur ma machine Ubuntu, j'obtenais le même résultat que le questionneur sans aucune chance de tuer le processus. Une deuxième machine testant la même chose dans une machine virtuelle Ubuntu s'est arrêtée de la même manière.
Videonauth
Un stracede l'ensemble du processus de l'autre côté n'a pas reproduit le résultat et cela sur ma machine et sur la machine d'un autre utilisateur. Bien sûr, il existe un mécanisme avec lequel vous pouvez tuer les applications qui ne répondent pas, mais si votre machine ne répond plus, il ne vous reste qu'une seule option, la réinitialiser. Je suis toujours en train de tester cela et avant de ne pas comprendre complètement ce qui cause le comportement décrit, je ne peux pas répondre à cette partie de la question.
Videonauth
C'est probablement une différence dans les configurations du noyau, comme un ordonnanceur différent qui priorise les E / S, ou des différences dans le pilote de disque / système de fichiers entre les systèmes. C'est bon de voir l'enquête que vous avez faite, c'est une bonne information.
Steve
Si vous êtes intéressé par un autre point de données; J'ai essayé cela sur une machine CentOS avec un fichier assez petit, et cela a fait exactement la même chose que ma solution éponge ci-dessous. J'imagine que pour un petit fichier sedva tamponner le tout dans la mémoire puis le fermer, plutôt que de garder la poignée. Avec un fichier de ~ 100 Mo, comme dans OP, il a augmenté indéfiniment mais n'a pas brisé la machine.
ymbirtt