Почему распаковка этого tgz выдает ошибку на моем Mac, а не на Linux?

27

У меня довольно странная проблема, и я не могу понять, что происходит. У меня есть файл tgz, scip-3.2.0.tgz , который выдает ошибку при попытке распаковать его. Ошибка происходит только на OS X (я на 10.10.4). Я могу извлечь файл без ошибок на Linux-машине под управлением CentOS 6.6. Ошибка возникает как при использовании командной строки, так tarи при использовании утилиты архивирования. Я отправил по электронной почте список рассылки SCIP, и у меня тот же хэш SHA-1, что и у другого пользователя ( e085a4a3591eddf945dcb365d97d2512c267e374), поэтому не было ошибки загрузки. Они не уверены, что происходит.

Вот ошибка, которую я получаю при попытке распаковать с помощью утилиты архивирования:

ошибка утилиты архивирования

В случае, если изображение когда-либо будет повреждено, текст на изображении говорит это:

Невозможно развернуть "scip-3.2.0.tgz" в "Рабочий стол".
(Ошибка 1 - операция не разрешена.)

И когда я пытаюсь распаковать через командную строку, это вывод, который я получаю . Это последняя строка ( tar: Error exit delayed from previous errors.), которая касается меня. Я не понимаю, что вызывает это. Архив, кажется, извлекается без проблем, но я не доверяю ему с этой ошибкой.

Кто-нибудь знает, что вызывает это?

[править]
Посмотрев немного ближе к выводу, строка 1108 содержит ошибку:

x scip-3.2.0/applications/Coloring/Makefile: Can't create 'scip-3.2.0/applications/Coloring/Makefile'
Geoff
источник
2
Работает ли это с другим приложением, таким как unarchiver? wakaba.c3.cx/s/apps/unarchiver.html
TryTryAgain
Да, это так! Интересно, что они делают по-другому. Частично проблема заключается в том, что у меня есть bash-скрипт, который автоматизирует кучу вещей, и одна из вещей, которые ему нужно сделать, - извлечь этот tgz, чтобы он мог построить то, что внутри него. Интересно, есть ли ошибка в tarкоманде, которая идет с OS X.
Джефф
1
Вполне возможно, есть ошибка. Я обнаружил, что встроенная утилита архивирования OS X довольно дурацкая. Нет ли способа переархивировать нужные файлы в zip или что-то еще? Кроме того, если вы пишете сценарий, возникает ли ошибка также gunzip -c scip-3.2.0.tgz | tar xopf -из командной строки, как вы бы использовали ее для сценария?
TryTryAgain
Да, эта команда выдает ту же ошибку. gunzipработает просто отлично, но когда я пытаюсь извлечь несжатый архив, возникает ошибка.
Джефф
Ах, оказывается, в tarball действительно была ошибка! Я не сумасшедший. Я напишу более подробный ответ. Очевидно утилита tar в OS X была правильной здесь!
Джефф

Ответы:

32

Это должно помочь определить, что происходит в ответе Джонни , а также ответить на вопрос, почему это работает в Linux, но не в Mac.

Проблема заключается в том, что Mac OS X использует bsdtar, в то время как большинство систем Linux используют gnutar.

Вы можете установить gnutarна Mac с Homebrew, используя brew install gnu-tar, который будет символическая ссылкаgnutar в/usr/local/bin качество gtar.

Если вы установили gnutar, то вы можете воспроизвести проблему, используя шаги в ответе Джонни .

$ brew install gnu-tar
==> Downloading https://homebrew.bintray.com/bottles/gnu-tar-1.28.yosemite.bottle.2.tar.gz
######################################################################## 100.0%
==> Pouring gnu-tar-1.28.yosemite.bottle.2.tar.gz
==> Caveats
gnu-tar has been installed as "gtar".

If you really need to use it as "tar", you can add a "gnubin" directory
to your PATH from your bashrc like:

    PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
==> Summary
🍺  /usr/local/Cellar/gnu-tar/1.28: 13 files, 1.6M
$ mkdir test
$ touch test/a test/b
$ gtar -zcvf test.tar.gz test test/a # make the archive with gnutar
test/
test/a
test/b
test/a
$ gtar -ztvf test.tar.gz
drwxr-xr-x adamliter/staff   0 2015-07-28 22:41 test/
-rw-r--r-- adamliter/staff   0 2015-07-28 22:41 test/a
-rw-r--r-- adamliter/staff   0 2015-07-28 22:41 test/b
hrw-r--r-- adamliter/staff   0 2015-07-28 22:41 test/a link to test/a
$ rm -r test
$ tar -xvf test.tar.gz # try to unpack the archive with bsdtar
x test/
x test/a
x test/b
x test/a: Can't create 'test/a'
tar: Error exit delayed from previous errors.
$ echo $?
1

Очевидно, что все gnutarархивируется по-разному, что приводит bsdtarк удушению дубликатов. Факт, который gtar -ztvf test.tar.gzуказывает на то, что второй экземпляр test/aархивируется как a, link to test/aимеет значение. Как отмечает Джонни в комментариях, gnutarдубликаты будут храниться в виде жестких ссылок, а не фактического файла, который можно отключить с помощью --hard-dereference.

То есть вы могли бы сделать следующее:

$ mkdir test
$ touch test/a test/b
$ gtar -zcvf test.tar.gz test test/a --hard-dereference
test/
test/a
test/b
test/a
$ gtar -ztvf test.tar.gz test
drwxr-xr-x adamliter/staff   0 2015-07-28 23:49 test/
-rw-r--r-- adamliter/staff   0 2015-07-28 23:49 test/a
-rw-r--r-- adamliter/staff   0 2015-07-28 23:49 test/b
-rw-r--r-- adamliter/staff   0 2015-07-28 23:49 test/a # note that this is no longer a link
$ rm -r test
$ tar -xvf test.tar.gz # unpack with bsdtar
x test/
x test/a
x test/b
x test/a
$ echo $?
0
$ ls test/
a b

Однако в этом случае вы явно не контролируете создание архива, так что --hard-dereferenceэто не вариант. К счастью, основываясь на ответе OP , кажется, что эта проблема была исправлена ​​апстримом.

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

Как только вы определите, что такое дубликат файла, вы можете использовать --fast-readопцию bsdtar(обратите внимание, что эта опция только часть bsdtar, а не gnutar ):

 -q (--fast-read)
         (x and t mode only) Extract or list only the first archive entry that matches each pattern or filename operand.  Exit as soon as each specified pat-
         tern or filename has been matched.  By default, the archive is always read to the very end, since there can be multiple entries with the same name
         and, by convention, later entries overwrite earlier entries.  This option is provided as a performance optimization.

Так, в примере игрушек , который я создал , следуя примеру игрушек в ответ Джонни , дубликат файла test/a. Таким образом, вы можете избежать этой проблемы, выполнив следующие действия:

# this set of commands picks up from the first set of commands
# i.e., the following assumes a tarball that was *not* made with
# the --hard-dereference option, although this will work just as well
# with one that was
$ tar -xvqf test.tar.gz test/a # unarchive the first instance of test/a
x test/a
$ tar -xvf test.tar.gz --exclude test/a # unarchive everything except test/a
x test/
x test/b
$ echo $?
0
$ ls test/
a b

Кроме того, обратите внимание, что он gnutarочень рад распаковать архив с дубликатами, которые были созданы самим собой, даже если этот --hard-dereferenceпараметр не использовался:

$ rm -r test
$ gtar -xvf test.tar.gz
test/
test/a
test/b
test/a
$ echo $?
0
$ ls test/
a b

Так что это отвечает на ваш вопрос о том, почему выдается ошибка на Mac, но не на Linux. (Большинство) дистрибутивов Linux поставляются вместе gnutar, и, поскольку, по-видимому, пакет был упакован gnutar, при распаковке gnutarне будет ошибки, но при распаковке будет ошибка bsdtar.


Для дальнейшего чтения и ссылки, возможно, стоит взглянуть на различия между bsdtar и GNU tar? на Unix.SE.

Адам Литер
источник
Ух ты, приятный сон, я понятия не имел, что между gnutar и bsd tar есть какая-то существенная разница. Исходя из вашего gtar -tcvf, gnutar достаточно «умен», чтобы оптимизировать второй файл копии как ссылку, а не дублировать его в архиве.
Джонни
После просмотра документов, похоже, что это побочный эффект обработки жестких ссылок в gtar. Кажется, кажется, что дублированный файл на самом деле является жесткой ссылкой на файл, поэтому он сохраняет его как ссылку, а не как фактический файл. Предоставление --hard-dereferenceопции gtar отключает это поведение.
Джонни
@Johnny Это действительно два из тех, кто поддерживал Homebrew, это выяснили (Мисти Де Мео и Доминик Тиллер). Сопровождающий некоторые программы, которые я использую, выпустил новую версию с дубликатом файла в tarball, что вызвало проблемы при попытке установить новую версию с Homebrew (очевидно). В любом случае, спасибо за ознакомление с документами! Я добавлю это к ответу.
Адам Литер
Это отлично. Я отмечаю этот ответ, так как это наиболее полное объяснение того, что происходит. Благодарность!
Джефф
7

Наличие дубликата файла в архиве не должно делать его недействительным или невозможным для извлечения в OSX, так как по умолчанию tar перезаписывает дубликаты.

Итак, я немного смущен поведение в вашем Gist - OSX деготь позволяет дубликаты файлов в архиве (возврат к первоначальной цели в виде т обезьяна ар зубчика утилиты, так что это позволяет файлы , которые будут добавляться в конце архив ленты, и при восстановлении архива самая новая версия файла перезапишет старую версию (и))

Только когда указана опция -k, tar должен предупреждать о существующих файлах.

Здесь я создал архив с дубликатом файла, а затем извлек его без проблем. Только когда я добавил параметр -k, он предупредил меня о дубликате файла:

Macbook> tar --version
bsdtar 2.8.3 - libarchive 2.8.3
Macbook> mkdir test
Macbook> touch test/a test/b
Macbook> tar -zcvf test.tar.gz test test/a
a test
a test/a
a test/b
a test/a
Macbook> tar -ztvf test.tar.gz
drwxr-xr-x  0 user group       0 Jul 28 10:42 test/
-rw-r--r--  0 user group       0 Jul 28 10:42 test/a
-rw-r--r--  0 user group       0 Jul 28 10:42 test/b
-rw-r--r--  0 user group       0 Jul 28 10:42 test/a
Macbook> rm -r test
Macbook> tar -xvf test.tar.gz
x test/
x test/a
x test/b
x test/a
Macbook> echo $?
0
Macbook> rm -r test
Macbook> tar -k -xvf test.tar.gz
x test/
x test/a
x test/b
x test/a: Already exists
tar: Error exit delayed from previous errors.
Macbook> echo $?
1

Простая проблема с umask тоже не кажется виновной, я попытался изменить свой umask на 0777, и я все еще могу извлечь архив:

Macbook> tar -xvf test.tar
x test/
x test/a
x test/b
x test/a
Macbook> ls -l test
ls: test: Permission denied
Macbook> sudo ls -l test
total 0
----------  1 someuser  wheel  0 Jul 28 13:48 a
----------  1 someuser  wheel  0 Jul 28 13:48 b

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

Macbook> mkdir -p testdir1/test testdir2/test
Macbook> touch testdir1/test/{a,b} testdir2/test/a
Macbook> chmod -w testdir2/test
Macbook> touch testdir2/test/b
touch: testdir2/test/b: Permission denied
Macbook> find testdir* -ls  | awk '{print $3, $11}'
drwxrwx--- testdir1
drwxrwx--- testdir1/test
-rw-rw---- testdir1/test/a
-rw-rw---- testdir1/test/b
drwxrwx--- testdir2
dr-xr-x--- testdir2/test
-rw-rw---- testdir2/test/a
Macbook> cd testdir1
Macbook> tar -cvf ../test.tar test/*
a test/a
a test/b
Macbook> cd ../testdir2
Macbook> tar -rvf ../test.tar test
a test
a test/a
Macbook> cd ..
Macbook> tar -tvf ./test.tar
-rw-rw----  0 username groupname       0 Jul 28 15:40 test/a
-rw-rw----  0 username groupname       0 Jul 28 15:40 test/b
-rw-rw----  0 username groupname       0 Jul 28 15:40 test/a
dr-xr-x---  0 username groupname       0 Jul 28 15:40 test/
-rw-rw----  0 username groupname       0 Jul 28 15:40 test/a
Macbook> tar -xvf test.tar
x test/a
x test/b
x test/a
x test/
x test/a
Macbook> 

Я также попытался изменить разрешения для test / a на 000, добавить его в архив, а затем добавить еще один test / a, но он тоже работал нормально:

drwxrwx---  0 username groupname       0 Jul 28 15:40 test/
-rw-rw----  0 username groupname       0 Jul 28 15:40 test/a
-rw-rw----  0 username groupname       0 Jul 28 15:40 test/b
dr-xr-x---  0 username groupname       0 Jul 28 15:40 test/
----------  0 username groupname       0 Jul 28 15:40 test/a
-rw-rw----  0 username groupname       0 Jul 28 15:40 test/a

Поэтому мне бы очень хотелось увидеть оригинальный архив, вызвавший проблему, и посмотреть, что могло быть в этом архиве, чтобы вызвать эту проблему.

Если имя файла и каталога имеют одно и то же имя, у tar действительно есть проблема с извлечением, но у него довольно четкое сообщение об ошибке:

Macbook> tar -xvf test.tar
x test/
x test/dir1/
x test/dir1/a
x test/
x test/dir1: Can't remove already-existing dir
tar: Error exit delayed from previous errors.

(если конфликт произошел наоборот, то есть файл появился первым, то каталог с таким же именем появился позже, tar просто удаляет его и создает каталог:

Macbook> tar -xvf test.tar
x test/
x test/dir1
x test/
x test/dir1/
x test/dir1/a
Джонни
источник
1
Я сделал немного более ясным, что поведение в его Gist (и его самоответ) не является полным ответом, потому что дубликаты файлов разрешены в архиве tar. Поэтому ответ «Я не могу распаковать архив tar с дублированным файлом» не должен быть «Удалить дубликат файла», так как tar должен быть в состоянии справиться с этим случаем.
Джонни
2
Это действительно комментарий - он не предлагает решение, это всего лишь обсуждение существующего решения. Джонни, можешь переместить это в комментарий? Я вернусь и удалю это позже, просто хотел дать вам шанс переместить его первым. Спасибо.
Ян С.
2
@Johnny, эта информация действительно имеет супер-ценную информацию, но это не ответ на вопрос. Это комментарий к другому ответу. Подумайте об этом так: если ответ Джеффа будет удален, будет ли этот ответ полезным? Нет, не будет. Действительно, содержание этого ответа «этот другой ответ Джеффа кажется неправильным». Первоначальный вопрос был «Что является причиной этой ошибки?» Самое близкое, что вы могли получить к ответу: «Я не знаю, что его вызывает, но это не дубликат файла» - но это потребует редактирования, и все еще не отвечает на первоначальный вопрос.
DW
2
Я бы предпочел, чтобы это не было удалено, поскольку большая картина - это место, где нужно учиться, а детали в этом посте превосходны по IMO. +1 и удаление не требуется - я думаю, что это поможет другим в подобной ситуации разобраться, если у них нет поврежденного файла OP или взаимодействие с коррупцией отличается, нет?
bmike
2
@bmike и другие: я добавил ответ, который должен хотя бы объяснить, что здесь происходит, хотя и не обязательно почему.
Адам Литер
6

Оказывается, утилита OS X tar была правильной! В архиве действительно была ошибка. Эта ветка электронной почты обсуждает это более подробно, но проблема в том, что в архиве есть дубликат файла . Ребята из SCIP исправляют архив, когда я это печатаю.

[edit]
Недавно обновленный scip-3.2.0.tgz теперь распаковывается просто отлично! Хэш SHA-1 нового tgz5b4e8283f4a5bf9e50f9a62d4320d6f5f50c8476 .

[править 2]
Дело не в том, что в архиве есть ошибка. Это просто то bsdtar, что поставляется с OS X, обрабатывает дубликаты файлов иначе, чем в gnutarLinux. Ответ Адама Литера здесь дает подробное объяснение того, что происходит.

Geoff
источник
1
Интересный. Так что, может быть, другие утилиты игнорировали ошибку дублирующегося файла и не жаловались? В любом случае, рад, что вы нашли причину и ответ.
TryTryAgain
1
Да, я думаю, что это именно то, что делают другие утилиты. Я бы сказал, что утилита tar OS X здесь правильная. Искаженный архив всегда должен вызывать хотя бы предупреждение, чтобы предупредить пользователя о том, что что-то не так. Спасибо за вашу помощь!
Джефф
Двойной файл в архиве tar не делает его искаженным архивом, формат tar специально разрешает дублирование. Мне любопытно, почему ваш mac tar отказался от распаковки архива, даже если вы не указали -kопцию, которая предупреждала бы о существующих файлах. К сожалению, они уже обновили scip-3.2.0.tgzфайл, чтобы удалить дубли, поэтому я не могу проверить этот архив.
Джонни
tarЭкстракт по- разному реагирует на попытку извлечь scip-3.2.0/applications/Coloring/Makefileдва раза в зависимости от вашего umask. Если 1-й созданный не оставляет вам права на запись, 2-я попытка не удалась.
дан
1
@WW Я добавил ответ, который объясняет, почему это не противоречие.
Адам Литер
1

Есть альтернативное, бесплатное, легкое архивное программное обеспечение, которое я использую для Mac OSX. Он называется Keka, и я использую его для распаковки 7zip наиболее конкретно. Более того, он может распаковывать другие типы, такие как .rar, .tar, .gz и т. Д. Он также работал для конкретного tar-файла OP, но я попытался сделать это после того, как @Geoff упомянул, что команда работает над исправлением файла.

ThisClark
источник