Скрипт отлично работает на устройствах коллег, но выдает мне «Недопустимую межустройственную ссылку»

#shell #docker-desktop

#оболочка #docker-рабочий стол

Вопрос:

Мой скрипт отлично работает на устройствах коллег (MacOSX с Docker Desktop, таким же, как у меня), но каждый раз выдает мне одну и ту же ошибку, и он не перемещает или только половину библиотек в deps каталоге:

 OSError: [Errno 18] Invalid cross-device link: '/tmp/pip-target-dzwe_2kc/lib/python/numpy' ->
 '/foo/python/numpy'
  

Мой сценарий :

 #!/bin/bash
export PKG_DIR='python'
export SIDE_DEPS_DIR='deps'

rm -rf ${PKG_DIR} amp;amp; mkdir -p ${PKG_DIR}
rm -rf ${SIDE_DEPS_DIR} amp;amp; mkdir -p ${SIDE_DEPS_DIR}

docker run --rm -v $(pwd):/foo -w /foo lambci/lambda:build-python3.8 
    pip3 install -r requirements.txt -t ${PKG_DIR}

# move stuff to deps
find /${PKG_DIR} -maxdepth 1 -type d 
( -name "pandas*" -o -name "numpy*" -o -name "numpy.libs*" -o -name "scipy*" -o -name "scipy.libs*" ) -exec mv '{}' ${SIDE_DEPS_DIR} ;

# zip side dependencies
zip -r ge_deps.zip deps
# zip layer
zip -r layers-python38-great-expectations.zip python

  

Это скрипт, который использует общедоступный образ lambda docker для создания слоя lambda (в основном zip, содержащий библиотеки) и который удаляет ненужные библиотеки, чтобы поместить их в другую папку deps .

Приведенный выше код будет использовать общедоступный образ Docker lambci / lambda и установит в пустой python каталог библиотеки, которые поступают из пакета python, который называется «большие ожидания» и который помогает тестировать конвейеры данных (что указано в requirements.txt и есть great-expectations==0.12.7 )

Я некоторое время сталкивался с этой проблемой и не нашел решения.

Комментарии:

1. кажется, у вас могут возникнуть некоторые проблемы с жесткими ссылками: unix.stackexchange.com/questions/79132 /…

2. Случайно ли вы какую- ln либо из папок, упомянутых в ошибке? И забыли -s флаг?

3. Я не связывал ни одну папку

4. Если источник и место назначения находятся в разных файловых системах, это ошибка, которую вы получите, если попытаетесь использовать rename(2) для ее перемещения, но AFAIK mv(1) должен вернуться к копированию, а затем удалению в этом случае. Есть ли у ваших коллег /tmp и /foo в той же файловой системе?

5. Я видел, что если я создаю новый каталог в / Users / random_name , он работает нормально. но если я запускаю скрипт несколько раз в одном и том же каталоге, он больше не работает, или если я создаю новый каталог в Users / random_name / Desktop, он не работает. И каталоги имеют права доступа

Ответ №1:

Только что возникла эта точная проблема.

/tmp и / foo — это разные устройства — / tmp находится в ОС docker, а / foo сопоставлен с вашей локальной ОС.

похоже, что pip использует shutil.rename() для перемещения созданного пакета из tmp в конечное местоположение вывода (/foo ). Это сбой, потому что это разные устройства. В идеале pip вместо этого использовал бы shutil.move() , который будет иметь дело с перемещением между устройствами.

В качестве обходного пути вы можете изменить временную папку, используемую PIP, установив TMPDIR перед вызовом команды pip. т. е. export TMPDIR=/foo/tmp Перед вызовом pip в образе docker. Итак, вся команда может быть примерно такой

 docker run --rm -v $(pwd):/foo -w /foo lambci/lambda:build-python3.8 
    /bin/bash -c "export TMPDIR=/foo/tmp amp;amp; pip3 install -r requirements.txt -t ${PKG_DIR}"
  

(несколько команд взяты из https://www.edureka.co/community/10736/how-to-run-multiple-commands-in-docker-at-once — открыт для лучших предложений!)

Вероятно, это будет медленнее, потому что для временных файлов используется локальная ОС, но это позволяет избежать попытки «переименования» между устройствами из папки temp в конечную выходную папку.