Команда оболочки grep запись из .Файл TAR, содержащий файлы .GZ

#shell #tar #archive

Вопрос:

Я пытаюсь извлечь строку из определенного файла .gz в архивированный файл .tar.

Содержимое этого tar файла содержит архив для каждого хоста, который выглядит примерно так:

 APPLOG/cp13ap011/logs/domeus.log.2021-07-09.gz
APPLOG/cp15ap043/logs/domeus.log.2021-07-09.gz
APPLOG/cp14ap411/logs/domeus.log.2021-07-09.gz
APPLOG/cp11ap231/logs/domeus.log.2021-07-09.gz
 

Я определил местоположение файла
find /backup/tmp/ -type f -name 'APPLOG-P10-2021-07-09.tar' |xargs zgrep -F 'communicationId=6700409965' >> ~/tmp/2021_07_09.txt

Когда я понял, что это файл .tar, содержащий запись в демонстрационных версиях

tar -tf APPLOG-P10-2021-07-09.tar -O |find APPLOG/ -type f -name 'domeus.log.2021-07-09*' | xargs zgrep -E "Id=6700409965" >> ~/tmp/2021_07_09.txt

Файл находится APPLOG/domeus.log.2021-07-09.gz здесь, есть несколько компьютеров, на которых хранится запись, но все машины будут иметь дублированное имя файла domeus.log.2021-07-09 *, а файл большой, поэтому ему необходимо уточнить строку "Id=6700409965"

В итоге я не получаю результат этих файлов

-rw-r—r— 10 ноября 15 16:58 2021_07_09.txt

Хитрость в том, что я не хочу разархивировать файл, если нет других вариантов

Комментарии:

1. tar | find в этом нет никакого смысла. find не считывает данные из stdin, поэтому он не увидит, что что-либо tar отправляет его.

2. Насколько важно сделать это эффективно? Если это очень важно, я бы использовал другой язык, например Python, где tarfile модуль позволяет вам делать все это за один проход. Простые способы сделать это в bash включают чтение вашего входного файла дважды (один раз, чтобы получить доступные имена, один раз, чтобы извлечь содержимое с конкретными именами, которые вас интересуют).

3. @CharlesDuffy, я бы с удовольствием это сделал, но у меня едва ли есть доступ, чтобы что-то делать с нашей резервной копией

4. Я не знаю, что вы имеете в виду: у вас нет доступа. Вы имеете в виду, что у вас нет доступного интерпретатора Python? (Это было бы удивительно в современной системе; Python встроен в большинство дистрибутивов Linux уже около 20 лет).

5. @MartinSchapendonk, верно, вопрос в том, имеет ли OP полное имя этого конкретного файла gz перед запуском. (Если бы они это сделали, зачем find им вообще использовать?)

Ответ №1:

К сожалению, выполнение этого в bash потребует нескольких проходов — это было бы намного эффективнее в Python, где tarfile модуль позволяет вам как решать, какие файлы вы хотите проверить, так и читать содержимое этих файлов за один проход.

 while IFS= read -r -d '' tarfile; do
  tar -xf "$tarfile" -T <(
    tar -tf "$tarfile" |
      grep -E 'APPLOG/(.*)/logs/domeus[.]log[.]2021-07-09[.]gz'
  ) -O |
    gunzip -c |
    grep 'Id=6700409965'
done < <(find /backup/tmp/ -type f -name 'APPLOG-P10-2021-07-09.tar' -print0) 
     >~/tmp/2021_07_09.txt
 

Предоставление документации по отдельным используемым методам:

  • while read циклы подробно обсуждаются в BashFAQ # 1 .
  • <(...) синтаксис подстановки процесса — он расширяется до имени файла, из которого ... можно считывать выходные данные, что на современных платформах реализовано с именованным каналом или эквивалентом (так что содержимое не нужно записывать на диск, и процессы могут выполняться параллельно).
  • tar -T ожидает, что следующим аргументом будет список имен файлов для работы.

Комментарии:

1. tar: для параметра требуется аргумент — ‘C’ Попробуйте ‘tar —help’ или ‘tar —usage’ для получения дополнительной информации. gzip: stdin: неожиданный конец файла

2. Извините, это должно было быть -O , а не -C .

3. @Haitham, прошло несколько дней, поэтому мне любопытно, где вы находитесь — если у ваших сотрудников devops был лучший подход, есть ли шанс, что он может появиться в качестве ответа здесь? И вы пробовали повторный запуск после исправления -O / -C thinko ?