Почему перенаправление вывода sed в один и тот же входной файл приводит к тому, что мой компьютер не отвечает?

13

Я пытался sedзаменить некоторые ключевые слова в большом файле (100 МБ). Я не знал о -iопции (inplace), поэтому моей первой попыткой было перенаправление следующим образом:

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

после этого мой компьютер остановился, почти не было ввода с клавиатуры. Я попробовал другую консоль Ctrl+ Alt+ , F1но после того, как медленно ввод имени пользователя, он остановился тоже. Без клавиатуры мой единственный вариант состоял в аппаратной перезагрузке машины. После входа в систему я увидел, что file.log был около 8 ГБ.

Я действительно хотел бы понять, почему выполнение этой команды могло сделать систему настолько безразличной, и если на системном уровне существуют механизмы для запуска предупреждений и прекращения процесса, вызывающего нарушение?

cesarpachon
источник
7
Это одноядерный компьютер? Кажется очень странным, что это должно было поставить современный компьютер на колени. Заправил свой диск, да. Израсходовал 100% одного из ваших ядер, да. Но полный крах?
тердон
В этом файле есть что-то особенное? если это не проблема, не могли бы вы опубликовать его содержимое в pastebin?
Сергей Колодяжный
Кроме того, каков объем вашей памяти? Не могли бы вы предоставить нам выход free -h ?
Сергей Колодяжный
Зачем использовать потоковый редактор в первую очередь, когда вы хотите изменить файл? ex -sc '%s/original/edited/ge|x' file.logследует делать то, что вы хотите в UNIX идиоматическим образом без sed -iпобочных эффектов.
Дэвид Онгаро
Обратите внимание, что даже если вы делаете это правильно (с помощью любого из методов, которые предоставляют люди), может быть рискованно делать подобные вещи с файлом журнала, принадлежащим активному процессу.
Random832

Ответы:

10

Как уже было сказано, он >>добавляется в файл, поэтому ваша sedкоманда будет сидеть там, читая только что выведенные строки, а затем выводить их еще. Если вы хотите , чтобы заменить файл на месте, >все еще не будет работать, но вы знаете о sed«S -iвариант, который, безусловно , тот , который вы хотите.

Однако, если вы абсолютно уверены, что хотите добавить файл, который вы читаете, в виде потока, и хотите сделать только один проход, рассмотрите возможность использования spongeиз moreutilsпакета;

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

spongeчитает из stdin в память до EOF, затем выводит все его содержимое в stdout, поэтому sedон достигнет конца файла, прекратит чтение, закроет его, а затем к нему добавится губка.

ymbirtt
источник
2
spongeэто хорошая утилита знать, но sedуже есть -iвариант: -i[SUFFIX], --in-place[=SUFFIX], edit files in place (makes backup if SUFFIX supplied).
Джошуа Тейлор
@JoshuaTaylor, OP использовал >>, который добавляет, а не >заменяет. Конечно, OP специально упомянул -iв этом посте, и это похоже на гораздо более распространенный вариант использования, чем этот, но я подумал, что стоит отметить, что опубликованная OP операция была возможна без особых ошибок, если вы действительно конечно, это то, что вы хотите сделать.
Ymbirtt
1
Я упомянул это здесь, потому что это был ключ в принятом ответе . Тем не менее, я буду искренне рад узнать о губке ; это новый инструмент для моего инструментария, и он заслуживает внимания.
Джошуа Тейлор
1
Ах! Понимаю. Я подправлю свой ответ, чтобы сделать его более понятным. Кроме того, если вам понравилось sponge, посмотрите на vipe. moreutilsэто просто волшебный пакет, наполненный вещами, которые вы никогда не знали, что вам нужно
ymbirtt
18

Ваша sedкоманда пыталась прочитать файл, к которому она добавлялась. Он никогда не достигнет конца файла, но потратит много времени процессора. Вот почему ^ C (процесс прерывания тока) был изобретен.

waltinator
источник
Я не думаю, что ^ C был вариант там ... он пошел в HALT, то есть не мигает курсор, застрял!
EKons
18

Добавление обратно к файлу, из которого вы читаете, ни в коем случае не является хорошей идеей, поскольку в результате вы получите постоянно растущий файл. Если вы действительно хотите записать обратно в файл, вы должны использовать -iфлаг:

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

или если вы хотите создать резервную копию перед внесением изменений, вы можете добавить суффикс файла к -iфлагу:

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

Это создаст файл с именем file.log.bakи затем внесет изменения, то, что вы сделали там, пытаясь добавить к файлу, из которого вы читаете, мы называем программистом сленг гонкой данных, где разные процессы стремятся к одному и тому же источнику данных, будь то ввод или вывод , По этой же причине ваша машина остановилась.

Videonauth
источник
1
Я удивлен, что это принятый ответ, потому что он даже не отвечает на вопрос ОП"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 По какой причине я остановился, но я обратился ко второй части, но вы правы. Я не обращался к этому, потому что я не знаю ответа на это. Мы протестировали команду после обсуждения в чате и пришли к совершенно разным результатам на разных машинах и в операционных системах. Пример: на машине с аркой он только позволяет файлу расти вечно, но не делает машину безразличной. На моей машине с Ubuntu я получал тот же результат, что и спрашивающий, не имея возможности убить процесс. Вторая машина, тестирующая то же самое на виртуальной машине Ubuntu, остановилась.
Видеонавт
straceВсего процесс на другой сторону didtn воспроизвести результат и это на моей машине и на машине другого пользователя. Конечно, есть механизм, с помощью которого вы можете убивать неотвечающие приложения, но если ваша машина перестает отвечать на запросы, у вас остается только одна опция, сбрасывающая ее. Я все еще проверяю это, и, прежде чем я не до конца понимаю, что является причиной описанного поведения, я не могу ответить на эту часть вопроса.
Видеонавт
Вероятно, это разница в конфигурациях ядра, например, в другом планировщике с приоритетом ввода-вывода, или различия в драйвере дисковой / файловой системы между системами. Приятно видеть, что вы, ребята, провели расследование, это хорошая информация.
Стив
Если вы заинтересованы в другой точке данных; Я попробовал это на компьютере CentOS с довольно маленьким файлом, и он сделал то же самое, что и мое решение для губки ниже. Я полагаю, что для небольшого файла sedбуферизует всю вещь в памяти и затем закрывает ее, вместо того, чтобы держать ручку. С файлом ~ 100 МБ, как в OP, он рос бесконечно, но никак не влиял на компьютер.
Ymbirtt