У меня есть автоматизированная сборка образов докеров, где я загружаю архив elasticsearch и извлекаю его через:
tar zxf archive.tar.gz --strip-components=1 -C /path/to/dir
И это всегда работало до последних выпусков (6.8.5 и 7.4.2). Он больше не работает в 6.8.5, что означает флаг --strip-components
больше не действует. Однако он отлично работает для 7.4.2. После сравнения этих двух архивов единственная разница, которую я обнаружил, заключается в том, что 6.8.5 имеет другое право собственности на файлы в архиве - 631:503
против root:root
в 7.4.2. Однако, если это была проблема, флаги --no-same-owner
или --user
должен был решить проблему, но они этого не сделали. Я даже создал пользователя / группу с этими идентификаторами и извлек архив под этим пользователем, но это тоже не повлияло.
Вот как вы можете воспроизвести (замените 6.8.5 на 7.4.2, чтобы попробовать оба):
$ docker run --rm -ti alpine:3.10.3 sh
### from the container
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.5.tar.gz
$ apk add --update tar
$ mkdir elastic
$ tar zxvf elasticsearch-6.8.5.tar.gz --strip-components=1 -C elastic
$ ls -la elastic
В 6.8.5 вы получите промежуточный каталог, который не был удален, в 7.4.2 вы его не увидите, хотя он существует в обоих архивах.
Как вы могли заметить, я не использую tar
из musl я использовал версию GNU из пакетов alpine (версия 1.32), которая существует уже несколько месяцев. Я использую этот пакет с теми же флагами во многих других сборках, и у меня он отлично работает.
Как это было объяснил для меня сотрудником Elastic на github это происходит из-за ведущего ./
по путям внутри архива:
/ # tar tvf elasticsearch-6.8.5.tar.gz --numeric-owner | head -n 2
drwxr-xr-x 631/503 0 2019-11-14 14:20 ./
drwxr-xr-x 631/503 0 2019-11-13 20:07 ./elasticsearch-6.8.5/
Итак, в этом случае --strip-components
должно быть 2, а не 1. Чтобы справиться с подобными ситуациями повсеместно, вы можете перечислить архив перед извлечением, и если он ./
вы можете динамически изменять --strip-components
количество:
$ if tar tf elasticsearch-6.8.5.tar.gz | head -n 1 | grep -q '^./$'; then STRIP_COMPONENTS_COUNT=2; else STRIP_COMPONENTS_COUNT=1; fi
$ tar zxvf elasticsearch-6.8.5.tar.gz --strip-components=$STRIP_COMPONENTS_COUNT -C elastic
Но, честно говоря, хорошие архивы надо создавать без всяких ./
что очень сбивает с толку, потому что, если вы не перечислите файлы в архиве, вы не заметите никакой разницы.