Почему извлечение этого tgz вызывает ошибку на моем Mac, но не на Linux?

У меня довольно странная проблема, и я не могу понять, что происходит. У меня есть файл 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'
Работает ли это с другим приложением, таким как разархиватор? wakaba.c3.cx/s/apps/unarchiver.html
Да, это так! Интересно, что они делают по-другому. Часть проблемы заключается в том, что у меня есть bash-скрипт, который автоматизирует кучу вещей, и одна из вещей, которую ему нужно сделать, это извлечь этот tgz, чтобы он мог построить то, что внутри него. Интересно, есть ли ошибка в tarкоманде, которая поставляется с OS X.
Вполне возможно, есть баг. Я обнаружил, что встроенная утилита архивации OS X довольно дрянная. Нет ли способа повторно заархивировать необходимые файлы в zip или что-то в этом роде? Кроме того, если вы создаете сценарий, возникает ли ошибка при gunzip -c scip-3.2.0.tgz | tar xopf -работе из командной строки, как если бы вы использовали ее для своего сценария?
Да, эта команда выдает ту же ошибку. gunzipработает нормально, но когда я пытаюсь извлечь несжатый архив, возникает ошибка.
А, оказывается, в архиве действительно была ошибка! Я не сумасшедший. Я напишу более подробный ответ. По-видимому, утилита tar в OS X была правильной здесь!
Что у вас umaskна 2 системах, на которых вы запускали это tar?
На моем Mac umaskэто 0022. На машине с Linux это 0002.

Ответы (4)

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

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

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

Если вы установите 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это не вариант. К счастью, судя по ответу ОП , кажется, что эта проблема была исправлена ​​восходящим потоком.

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

Как только вы определите, что представляет собой дубликат файла, вы можете использовать --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, и, поскольку tar-архив предположительно был упакован с gnutar, при распаковке с gnutar, не будет ошибки, но будет ошибка при распаковке с bsdtar.


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

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

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

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

Только при наличии параметра "-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
Привет, Джонни, похоже, это не отвечает на вопрос. Какое решение вопроса вы предлагаете? Если бы вы могли отредактировать свой ответ, чтобы изложить подробное пошаговое описание, это было бы здорово. В противном случае это может быть лучше в качестве комментария к другому ответу, представленному в виде контекстной информации.
Я немного уточнил, что поведение в его Gist (и его самостоятельный ответ), по-видимому, не является полным ответом, потому что в tar-архиве разрешены дубликаты файлов. Таким образом, ответ на «Я не могу распаковать tar-архив с дубликатом файла» не должен быть «Удалите дубликат файла», поскольку предполагается, что tar может справиться с этим случаем.
Джонни - понял, и я ценю контекст, данный ситуации. Поскольку это больше похоже на метод воспроизведения проблемы, а не на решение, я все же предполагаю, что это может быть лучше в качестве комментария к самостоятельному ответу, а не самостоятельного ответа - хотя это полезно, он все же не пытается для решения проблемы, помимо объяснения того, что проблема является исключительно дубликатом (например, не включены шаги по исправлению, чтобы решить, как пользователь может обойти проблему и т. д.). Зато отличная детализация!
Это действительно комментарий - он не предлагает решение, это просто обсуждение существующего решения. Джонни, можешь переместить это в комментарий? Я вернусь и удалю это позже, просто хотел дать вам возможность сначала переместить его. Спасибо.
Хорошо, я уже оставил комментарий, не стесняйтесь удалить его, но я думаю, что этот ответ содержит некоторую ценную информацию, которой нет в ответе пользователя, поскольку простое наличие дублирующегося файла не должно приводить к сбою извлечения архива, поэтому следующий человек, который придет сюда с похожей проблемой, будет введен в заблуждение и будет думать, что у него нет другого выбора, кроме как удалить дубликат файла. Я думал, что ценность обмена стеками и голосования пользователей заключается в том, что менее качественные ответы могут остаться и предоставить некоторую дополнительную информацию, которую не дает самый популярный или принятый ответ.
@Джонни, в этой информации есть суперценная информация, но это не ответ на вопрос. Это комментарий к другому ответу. Подумайте об этом так: если бы ответ Джеффа был удален, был бы этот ответ полезен? Нет, не будет. Действительно, содержание этого ответа таково: «другой ответ Джеффа не кажется правильным». Первоначальный вопрос был «Что вызывает эту ошибку?» Самый близкий ответ, который вы могли бы получить, был «Я не знаю, что вызывает это, но это не дубликат файла», но это потребовало бы редактирования и по-прежнему не отвечает на исходный вопрос.
@DW Конечно, этот «ответ» лучше было бы написать в виде комментария, но в комментарии мало места. Подумайте об этом так: если бы ответ Джеффа был единственным ответом, он был бы неполным или даже вводящим в заблуждение. Если он пересматривает свой ответ, то было бы правильнее удалить этот.
Я бы предпочел, чтобы это не было удалено, поскольку в целом это место для изучения, и детали в этом посте превосходны. +1 и удалять не нужно - я думаю, это поможет другим в аналогичной ситуации разобраться, если у них нет поврежденного файла OP или взаимодействие с повреждением отличается, не так ли?
@bmike и другие: я добавил ответ , который должен хотя бы объяснить, что здесь происходит, хотя и не обязательно почему.
Спасибо @Johnny за его тщательный анализ того, что здесь происходит!

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

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

[править 2]
Дело не в том, что в архиве ошибка. Просто bsdtar, который поставляется с OS X, обрабатывает повторяющиеся файлы иначе, чем gnutar, который поставляется с Linux. Ответ @Adam Liter здесь дает подробное объяснение того, что происходит.

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

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