Объединить несколько tar-файлов в одну команду

Объединить несколько tar-файлов в одну команду

Я получаю от 4 до 100 очень больших архивных файлов tar (~20 ГБ) каждый день. Раньше я объединял их, проходя по каждому из архивов, которые я вижу в файловой системе, и делая что-то вроде этого

/bin/tar -concatenate --file=allTars.tar receivedTar.tar

Проблема в том, что по мере объединения все большего количества файлов tar, он должен прочитать до конца, allTars.tarчтобы начать объединение снова. Иногда требуется более 20 минут, чтобы начать добавлять еще один файл tar. Это слишком медленно, и я пропускаю согласованное время доставки полного allTars.tar.

Я также попробовал передать команде tar список файлов следующим образом:

/bin/tar --concatenate --file=alltars.tar receiverTar1.tar receivedTar2.tar receivedTar3.tar...etc

Это дало очень странные результаты. allTars.tarРазмер должен был соответствовать ожидаемому (т. е. близко к receivedTar.tarсумме размеров всех файлов), но при allTars.tarраспаковке файлы, похоже, были перезаписаны.

Есть ли способ объединить все эти tar-файлы в одну команду, чтобы не приходилось каждый раз читать до конца объединяемого архива?иправильно ли они распакованы и со всеми файлами/данными?

решение1

Это может вам не помочь, но если вы готовы использовать эту -iопцию при извлечении из конечного архива, то вы можете просто catобъединить tar. Файл tar заканчивается заголовком, полным нулей, и еще большим количеством нулей до конца записи. С --concatenatetar необходимо пройти по всем заголовкам, чтобы найти точное положение конечного заголовка, чтобы начать перезапись там.

Если вы просто cattar, у вас просто есть дополнительные нули между заголовками. Эта -iопция просит tar игнорировать эти нули между заголовками. Так что вы можете

cat  receiverTar1.tar receivedTar2.tar ... >>alltars.tar
tar -itvf alltars.tar

Кроме того, ваш tar --concatenateпример должен работать. Однако, если у вас есть файл с одинаковым именем в нескольких архивах tar, вы перезапишете этот файл несколько раз, когда будете извлекать все из полученного tar.

решение2

Этот вопрос довольно старый, но я бы хотел, чтобы мне было легче найти следующую информацию раньше. Так что если кто-то еще наткнется на это, наслаждайтесь:

То, что Джефф описывает выше, является известной ошибкой в ​​gnu tar (сообщение об этом поступило в августе 2008 г.). Только первый архив (тот, что после опции -f) удаляет маркер EOF. Если вы попытаетесь объединить более 2 архивов, последний архив(ы) будет "скрыт" за маркерами конца файла.

Это ошибка в tar. Он объединяет целые архивы, включая конечные нулевые блоки, поэтому по умолчанию чтение полученного архива останавливается после первой конкатенации.

Источник:https://lists.gnu.org/archive/html/bug-tar/2008-08/msg00002.html (и последующие сообщения)

Учитывая возраст ошибки, я задаюсь вопросом, будет ли она когда-нибудь исправлена. Я сомневаюсь, что есть критическая масса, которая затронута.

Лучшим способом обойти эту ошибку может быть использование этой -iопции, по крайней мере для файлов .tar в вашей файловой системе.

Как отмечает Джефф, tar --concatenateможет потребоваться много времени, чтобы достичь EOF, прежде чем он объединит следующий архив. Так что если вы собираетесь застрять с «сломанным» архивом, которому нужна опция tar -iдля распаковки, я предлагаю следующее:

Вместо использования tar --concatenate -f archive1.tar archive2.tar archive3.tar вам, вероятно, будет лучше бежать cat archive2.tar archive3.tar >> archive1.tarили pipe to dd, если вы собираетесь записывать на ленточное устройство. Также обратите внимание, что этомогпривести к неожиданному поведению, если ленты не были обнулены перед (пере)записью на них новых данных. По этой причине подход, который я собираюсь использовать в своем приложении, — это вложенные tar, как предлагается в комментариях под вопросом.

Вышеуказанное предложение основано на следующем очень небольшом контрольном образце:

time tar --concatenate -vf buffer.100025.tar buffer.100026.tar
  real  65m33.524s
  user  0m7.324s
  sys   2m50.399s

time cat buffer.100027.tar >> buffer.100028.tar
  real  46m34.101s
  user  0m0.853s
  sys   1m46.133s

Размер всех файлов buffer.*.tar составляет 100 ГБ, система практически простаивала, за исключением каждого из вызовов. Разница во времени достаточно существенна, поэтому я лично считаю этот бенчмарк валидным, несмотря на небольшой размер выборки, но вы свободны в своем собственном суждении об этом и, вероятно, лучше всего запустить такой бенчмарк на своем собственном оборудовании.

решение3

Как вы уже сказали, целевой архивный файл должен быть прочитан до конца, прежде чем к нему будет добавлен второй исходный архив. У GNU tar есть опция, -nкоторая предписывает ему предполагать, что файл доступен для поиска (помните, tar был разработан для ленточных и потоковых архивов, которые не доступны для поиска). GNU tar по умолчанию предположительно автоматически определяет, доступен ли файл, однако многие пользователи, такие как вы, могут сделать так, чтобы tar пропускал чтение полного содержимого каждой записи, добавив опцию -n:

tar -n --concatenate --file=target_file.tar  other_file.tar

Я не могу проверить (на момент написания), какие версии tar, если таковые имеются, будут работать так, как ожидается, для этой команды. Если другие пользователи имеют возможность доказать это решение, пожалуйста, прокомментируйте ниже, и я обновлю этот ответ соответствующим образом.

решение4

Поскольку конкатенация требует интенсивного ввода-вывода, я бы рекомендовал либо 3 SSD (1 ТБ) в RAID 0. Один SSD на sata 3 даст 500 МБ/с чтения и примерно столько же для записи. Дорого, да, но быстро x3.

Связанный контент