Por que redirecionar a saída sed para o mesmo arquivo de entrada faz minha máquina não responder?

13

Eu estava tentando sed substituir algumas palavras-chave em um arquivo grande (100 MB). Eu desconhecia a opção -i (inplace), então minha primeira tentativa foi redirecionar assim:

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

o que aconteceu depois disso foi que meu PC parou, quase sem entrada de teclado. Eu tentei um console diferente Ctrl + Alt + F1 mas depois de digitar lentamente o nome do usuário, ele parou também. Sem teclado, minha única opção era restaurar o hardware da máquina. Após o login, vi que file.log tinha cerca de 8 GB.

Eu realmente gostaria de entender por que a execução desse comando foi capaz de deixar o sistema sem resposta, e se existem mecanismos no nível do sistema para acionar alertas e matar o processo ofensivo?

    
por cesarpachon 06.07.2016 / 23:04

3 respostas

10

Como já foi dito, >> acrescenta ao arquivo, então o seu comando sed ficará lá lendo as linhas que acabou de gerar e, em seguida, emitindo-as um pouco mais. Se você quisesse substituir seu arquivo no local, > ainda não funcionaria, mas você está ciente da opção sed -i, que é definitivamente a que você deseja.

Se, no entanto, você tiver certeza absoluta de que deseja anexar a um arquivo que está lendo como um fluxo e só quiser fazer uma etapa disso, considere usar sponge do pacote moreutils package;

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

sponge lê de stdin na memória até EOF, então despeja todo o seu conteúdo para stdout, então sed irá atingir o final do arquivo, parará de lê-lo, fechá-lo e então a esponja começará a anexá-lo.

    
por ymbirtt 07.07.2016 / 13:02
18

Seu comando sed estava tentando ler o arquivo ao qual estava anexando. Ele nunca alcançará o End-Of-File, mas consumirá muito tempo de CPU. É por isso que ^ C (processo atual de interrupção) foi inventado.

    
por waltinator 06.07.2016 / 23:09
18

Anexar de volta ao arquivo que você leu não é, em hipótese alguma, uma boa ideia, pois você terá um arquivo cada vez maior. Se você realmente quiser escrever de volta no arquivo, use o sinalizador -i :

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

ou se você quiser criar um backup antes de fazer alterações, adicione um sufixo de arquivo ao sinal -i :

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

Isso criaria um arquivo chamado file.log.bak e, em seguida, faria alterações, o que você fez lá, tentando anexar ao arquivo que está lendo, chamamos de gíria do programador uma corrida de dados, onde diferentes processos competem pelos mesmos dados fonte seja entrada ou saída. É também por isso que a sua máquina parou.

    
por Videonauth 06.07.2016 / 23:19