Как предотвратить grep от чрезмерного ненужного использования памяти

То, что Вы просите, не тривиально. Это возможно, я просто не знаю существующую реализацию решения, в котором Вы нуждаетесь. AVFS, вероятно, не будет работать.

Существует, ищут-bzip (https://github.com/cscott/seek-bzip) и подобные проекты, которые пытаются обеспечить случайный доступ блока к архивам bzip2. Составление таблицы для этого сопроводит пока распаковка всей вещи; фактический ввод-вывод потребует, чтобы корректный блок был найден, несжатым и сохранен в памяти, и если это является необходимым снова позже, несжатым снова. Я в настоящее время не знаю ни о каком способе использовать то решение Вашей проблемы непосредственно, все же.

К моему знанию также нет никакой программы, которая взяла бы изображение файловой системы в канале (не seekable) и файлы извлечения из него.

Необходимо было бы реализовать это в NBD, предохранителе, или подобный. AVFS входит в то направление, но это не упоминает seekability bzip2 файлов. Если это не будет использовать эту технологию (и исходный код не похож на него), то это будет работать на небольшие файлы только или на приложение, которые читают всю линейную вещь (такой как cp или tar был бы). Любой произвольный доступ ввод-вывод (такой как Вы имеете со смонтированным изображением файловой системы) вытащил бы Вас из памяти или доступа, будет настолько медленным, это абсолютно неприменимо (т.е. это извлекло бы 450 ГБ данных для чтения 4k в конце диска).

Существует cloop но это не широко доступно (Knoppix только?) и это потребовало бы, чтобы Вы преобразовали свое существующее изображение bz2 в формат выстрела сначала. Если Вы делаете оперативное преобразование, и оно перестало работать, Вашего изображения не стало.

Иногда, покупка большего жесткого диска является предпочтительным решением.

2
30.10.2014, 00:44
1 ответ

У вас закончилась память, потому что grep ищет строку за строкой, а вы явно удалили все новые строки в вашем конвейере:

$ xxd -p /path/to/sda.img | tr -d '\n' | grep -ob '117a0cb17ada1002'

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

Следующий сценарий awk будет искать шаблон в последовательных строках и выводить на терминал позицию первого символа совпадения. Он предполагает, что ширина вводимых данных составляет ровно 60 символов (так же, как и вывод xxd -p).

{
    if (NR > 1 && offset = match(line $0, pattern)) {
        printf("%d: %s\n", (NR - 2)*60 + offset, pattern);
    }

    line = $0;
}

Или, альтернативно (но эквивалентно):

NR > 1 {
    if (offset = match(line $0, pattern)) {
        printf("%d: %s\n", (NR - 2)*60 + offset, pattern);
    }
}

{ line = $0 }

Тестирование на случайных входных данных (поисковые строки, которые я использую далее, выделены в данных):

$ xxd -p random.dat | head -n 5
b1a632f5218b1404d9873dc20ae80e687c99c618bfc0f92db007c36c2888
21a99d23914e34510b9ab8e1c2b340cf1e4a0585b788aecbbc64f01a7a52
62e1746ca1fa4ff65d575419522d52169c5d3f9eee0e204979d79634db9b
fa78320eb7b9e072adc53720785fc7b65a1ffb04cc77566686ea74ac00fe
f32afc1539690d0046bc13706404d82112442d4bc447ac95df1fe96cd4bd
$ xxd -p random.dat | awk -v pattern=b1a632f5 -f script.awk
1: b1a632f5

$ xxd -p random.dat | awk -v pattern=288821a9 -f script.awk
57: 288821a9

$ xxd -p random.dat | awk -v pattern=ac00fef3 -f script.awk
235: ac00fef3

Запуск на файле размером 1 терабайт будет медленным, независимо ни от чего. Его можно (возможно) ускорить, задав опцию -c 256 в xxd (и соответственно изменив 60 на 256 в скрипте awk), чтобы уменьшить количество совпадений шаблонов, но данные в каждой строке будут обязательно совпадать дважды (один раз вместе с предыдущей строкой, другой раз вместе со следующей).

7
27.01.2020, 21:52

Теги

Похожие вопросы