конвейер gitlab-CI: ошибка lftp 550 при попытке удалить файлы - PullRequest
2 голосов
/ 11 декабря 2019

Я использую бесплатные общие раннеры в среде gitlab.com. У меня есть конвейер gitlab-CI, который запускает следующие команды lftp одну за другой:

  • lftp -c "set ftp:ssl-allow no; open -u $USERNAME,$PASSWORD $HOST; glob -a rm -r ./httpdocs/*"
  • lftp -c "set ftp:ssl-allow no; open -u $USERNAME,$PASSWORD $HOST; mirror -R public/ httpdocs --ignore-time --parallel=50 --exclude-glob .git* --exclude .git/"

Цельиз этих команд следует удалить содержимое папки httpdocs (предыдущие файлы) и затем загрузить новый артефакт сборки.

Конвейер CI запускается из CMS. Иногда случается, что редакторы контента обновляют контент параллельно, что приводит к большому количеству триггеров, которые работают параллельно (конвейер занимает около 3 минут).

Затем конвейер начнет работать со следующей ошибкой:

rm: Ошибка доступа: 550 /httpdocs/build-html-styles.css: Нет такого файла или каталога

Это происходит из-за того, что файл удален другим конвейеромв очереди на удаление. Очень похожая ошибка возникает, когда папка httpdocs полностью пуста. Это приводит к сбою всего моего конвейера (вторая команда upload lftp вообще не выполняется).

Примеры неисправных конвейеров и их вывод:

Как предотвратить это? Использование lftp для загрузки артефакта не является обязательным - я запускаю образ докера node:8.10.0. Файл Gitlab-ci.yml , о котором идет речь.

Ответы [ 2 ]

1 голос
/ 14 декабря 2019

Я комментировал простую блокировку файла с простым ожиданием активного опроса. У меня нет опыта работы с lftp, но копаясь с разных интернет-ресурсов, таких как this , я написал следующее. Я вижу, что lftp не поддерживает блокировку файлов в протоколе, так что вы могли бы что-то вроде этого:

const="set ftp:ssl-allow no; open -u $USERNAME,$PASSWORD $HOST"
# wait until file exists
while lftp -c "$const; df lockfile"; do sleep 1; done
# create the lockfile
lftp -c "$const; mkdir lockfile"
# the work
lftp -c "$const; glob -a rm -r ./httpdocs/*"
lftp -c "$const; mirror -R public/ httpdocs  --ignore-time --parallel=50 --exclude-glob .git* --exclude .git/"
# remove lockfile
lftp -c "$const; rmdir lockfile"

Я использовал mkdir и rmdir и каталог вместо файла, потому что я не 'не знаю, как создать пустой файл с помощью lftp. Между поиском файла и его созданием все еще существует условие гонки, но оно должно защищать как минимум от двух одновременных обращений. Чтобы защитить больше, вы можете сделать что-то вроде sleep 0.$(printf "%02d" $((RANDOM / 10))) - сделать время ожидания случайным, чтобы они входили в создание файла менее «согласованно».

Также на всякий случай я бы не зеркалировал в каталог httpdocs, но к некоторому временному каталогу, например tmp=httpdocs_$(uuidgen); lftp "mirror .. $tmp", который впоследствии можно было бы переименовать в lftp 'rmdir httpdocs; rename $tmp httpdocs", чтобы сделать развертывание более безопасным с меньшим временем простоя (меньше времени при пустом httpdocs). В будущем я предлагаю перейти к более безопасному / более сложному протоколу соединения с удаленным сервером, который поддерживает блокировку файлов. Вроде сш. Или, может быть, самба.

0 голосов
/ 14 декабря 2019

lavv17/lftp выпуск 302 выступил за то, чтобы lftp пропустил такой контент, но он не получил никакой поддержки.

Список рассылки предлагает

Чтобы удалить каталог, используйте rmdir

В вашем случае: rm -rf httpdocs/ (затем mkdir httpdocs, если вам нужна пустая папка)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...