2015-06-02 2 views
2

ОбзорКак обрабатывать файлы с самых старых до новейших bash?

У меня есть куча файлов журнала, которые опрокидывании, когда они достигают определенного размера. Каждая строка в файле журнала содержит кучу форматирования журнала, а затем некоторую интересную информацию. Я хочу взять эти файлы и удалить форматирование с начала каждой строки, а затем поместить вывод всего этого в один файл. Затем я в конце концов возьму этот файл и загружу его в другое приложение вручную.

Подробности

Файловая структура выглядит следующим образом:

logs 
|-- modules 
| +-- ... 
|-- application.log 
|-- gc.log 
|-- gc.log.1 
|-- ... 
+-- gc.log.10 

Так logs содержит подкаталоги и несколько файлов журналов. Те, которые мне не нравятся, - gc.log*.

Каждый файл gc.log* переходит к новому файлу, когда он заполняется. gc.log всегда самый новый, и он доходит до gc.log.10, являющегося самым старым (по умолчанию всего 10, максимальная версия 9, но это настраивается).

Типичный gc.log* содержит тысячи записей, как:

INFO | jvm 1 | 2015/05/28 04:40:58 | 1164752.977: [GC pause (young), 0.06583700 secs] 
INFO | jvm 1 | 2015/05/28 04:40:58 | [Parallel Time: 45.2 ms] 
INFO | jvm 1 | 2015/05/28 04:40:58 |  [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
INFO | jvm 1 | 2015/05/28 04:40:58 |  Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 
... 

(Да это G1 журналы GC от Oracle JVM Именно эти, что мне нужно в отдельном файле, так что я могу построить график с GCViewer.)

После того, как я раздел форматирование, мне нужно, чтобы это выглядело как:

1164752.977: [GC pause (young), 0.06583700 secs] 
    [Parallel Time: 45.2 ms] 
     [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
     Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 

то, что я до сих пор

До сих пор я узнал, что я не должен использовать ls для получения файлов. Я нашел это на другом вопросе SO (извините, я забыл, какой) Why you shouldn't parse the output of ls(1).

Я использую следующий список файлов, а затем отсортировать их от старых к новым:

find "$logDir" -maxdepth 1 -type f -name 'gc.log*' | sort -Vr 

Что дает мне следующее:

./gc.log.10 
./gc.log.9 
./gc.log.8 
./gc.log.7 
./gc.log.6 
./gc.log.5 
./gc.log.4 
./gc.log.3 
./gc.log.2 
./gc.log.1 
./gc.log 

Команда, которую я должен удалить форматирование является:

sed -e 's/^.\{7\}[|].\{10\}[|].\{21\}[|] //g' 

(я могу просто использовать cut -c43-)

Проблема

Я не уверен, как получить выход из sort в sed.

Ниже не работает, когда имя файла (или $logDir) имеет пробелы:

find "$logDir" -maxdepth 1 -type f -name 'gc.log*' | sort -Vr | xargs sed -e "s/^.\{7\}[|].\{10\}[|].\{21\}[|] //g" 

Я также собираюсь нужно взять выход из sed, а затем объединить, что все вместе в единый файл.

Вопрос

Наконец вопрос:

  • Как я могу перечислить некоторые файлы в каталоге в обратном натуральном порядке сортировки, снимите шаблон с начала каждой строки в этих файлах и наконец, конкатенировать результаты в один файл (в bash)?
+0

У вас есть GNU 'find'? Если это так, мы можем использовать '-printf', чтобы поместить время модификации в вывод, предполагая, что это _really_, что вы хотите отсортировать. –

+0

BTW, написание эссе, а не хорошо изолированный вопрос (или пара/трио из них) несколько меньше идеала. Шансы на то, что кто-то еще захочет иметь возможность безопасно сортировать файлы с произвольным именем в mtime в сценарии оболочки, очень и очень высоки, поэтому вопрос, который задает только об этом (если он уже не существовал в этой теме), получит целое много просмотров/upvotes/ответов. Спрашивать, как делать все A, B и C вместе, означает, что вы задаете вопрос, где ответы полезны только вам, потому что почти никто не будет иметь одинаковый формат файла и c. –

+0

@EdMorton Извините, что это была ошибка копирования. Я переименовал их во время тестирования. Я обновил вопрос. – Steiny

ответ

1

В этом случае имена ваших файлов настолько просты и лет u're делает так мало с ними, я был бы соблазн просто использовать выход LS, предполагая, что ваши файлы имеют интуитивные прогрессивные времена изменений, то все, что вам понадобится это:

ls -rt gc.? gc | xargs awk -F' [|] ' '{print $NF}' > newfile 

Например:

$ cat gc 
INFO | jvm 1 | 2015/05/28 04:40:58 | 1164752.977: [GC pause (young), 0.06583700 secs] 
INFO | jvm 1 | 2015/05/28 04:40:58 | [Parallel Time: 45.2 ms] 
INFO | jvm 1 | 2015/05/28 04:40:58 |  [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
INFO | jvm 1 | 2015/05/28 04:40:58 |  Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 
$ 
$ cat gc.1 
INFO | jvm 1 | 2015/05/28 04:40:58 | 1234567.977: [GC pause (young), 0.06583700 secs] 
INFO | jvm 1 | 2015/05/28 04:40:58 | [Parallel Time: 45.2 ms] 
INFO | jvm 1 | 2015/05/28 04:40:58 |  [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
INFO | jvm 1 | 2015/05/28 04:40:58 |  Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 
$ 
$ cat gc.2 
INFO | jvm 1 | 2015/05/28 04:40:58 | 8889996.977: [GC pause (young), 0.06583700 secs] 
INFO | jvm 1 | 2015/05/28 04:40:58 | [Parallel Time: 45.2 ms] 
INFO | jvm 1 | 2015/05/28 04:40:58 |  [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
INFO | jvm 1 | 2015/05/28 04:40:58 |  Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 

$ ls -rt gc.? gc | xargs awk -F' [|] ' '{print $NF}' 
8889996.977: [GC pause (young), 0.06583700 secs] 
    [Parallel Time: 45.2 ms] 
     [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
     Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 
1234567.977: [GC pause (young), 0.06583700 secs] 
    [Parallel Time: 45.2 ms] 
     [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
     Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 
1164752.977: [GC pause (young), 0.06583700 secs] 
    [Parallel Time: 45.2 ms] 
     [GC Worker Start (ms): 1164752977.7 1164752977.7 1164752977.7 1164752977.9 
     Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff: 0.2] 
+0

Думаю, я пойду с чем-то подобным, потому что это легко понять. Кажется, что он не обрабатывает пространства, но сейчас все в порядке. Хотя в настоящее время я использую мой подход 'find' вместо' ls', и он выполняет задание (на самом деле временные метки, вероятно, хорошо, но для тестирования я создавал их в разных порядках). – Steiny

1

Поскольку ваши имена файлов фиксированы, вы можете просто использовать расширение распорка:

for wrapper in wrapper.log{.{9..1},}; do 
    echo "$wrapper" 
    # do whatever you want to do... 
done 

Для вашей цели, я думаю, это может работать тоже:

$ cat wrapper.log{.{9..1},} | sed ... 

Немного более общий вариант :

$ logfile="wrapper.log" # may contain spaces in filename 
$ cat "$logfile"{.{9..1},} | sed ... 
+0

А я раньше не видел расширения скобы. Похоже, что это может сработать, но что-то, что я забыл, было то, что количество файлов настраивается. По умолчанию их всего 10 (максимальная версия 9), но это не всегда так. – Steiny

+0

Для будущих читателей 'wrapper.log' ==' gc.log' (была ошибка копирования, которая была исправлена ​​в вопросе). – Steiny

+0

@ EdMorton Да, я согласен с сожалением. Я столкнулся с этим, проверяя, почему я использовал 'sort -Vr', но забыл обновить вопрос. – Steiny

1

Если вы хотите, чтобы сделать это правильно (и есть GNU find и sort), скажите find писать имена файлов предшествуют время изменения и разделенных символами NUL (единственный персонаж, который не может существовать в файле-х полностью квалифицированный путь в UNIX); используйте sort для сортировки по mtime (вместо того, чтобы пытаться испортить имена); а затем прочитайте оба фрагмента данных:

while IFS= read -r -d ' ' mtime && IFS= read -r -d '' filename; do 
    sed -e 's/^.\{7\}[|].\{10\}[|].\{21\}[|] //g' <"$filename" 
done < <(find "$logDir" -maxdepth 1 -type f -printf '%[email protected] %P\0' | sort -nz) 

Это будет обрабатывать файлы в порядке от старости до новейшей версии.

Смежные вопросы