gitlab-CI 管道:尝试删除文件时出现 lftp 错误 550

gitlab-CI pipeline: lftp error 550 when trying to delete files

我在 gitlab.com 环境中使用免费共享 运行 用户。我有一个 gitlab-CI 管道,运行 一个接一个地执行以下 lftp 命令:

这些命令的目的是删除 httpdocs 文件夹(以前的文件)的内容,然后上传新的构建工件。

CI 管道由 CMS 触发。有时会发生内容编辑器并行更新内容的情况,导致许多触发器并行 运行(管道大约需要 3 分钟才能完成)。

然后管道将开始失败并出现以下错误:

rm: Access failed: 550 /httpdocs/build-html-styles.css: No such file or directory

发生这种情况是因为另一个管道删除的文件正在排队等待删除。当 httpdocs 文件夹完全为空时,会发生非常类似的错误。这导致我的整个管道失败(第二个上传 lftp 命令根本没有执行)。

失败管道示例及其输出:

如何防止这种情况发生?使用 lftp 上传工件不是必须的 - 我正在 运行 宁 node:8.10.0 docker 图片。 Gitlab-ci.yml 有问题的文件。

lavv17/lftp issue 302 提倡 lftp 跳过此类内容,但没有获得任何支持。

mailing list suggests

To delete a directory use rmdir

在您的情况下:rm -rf httpdocs/(如果您需要空文件夹,则后跟 mkdir httpdocs

我在评论简单file locking with simple active polling waiting. I have no experience with lftp, but scrambling from various internet resources like 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"

我使用了 mkdirrmdir 以及目录而不是文件,因为我不知道如何使用 lftp 创建空文件。在查找文件和创建文件之间仍然存在竞争条件,但它至少应该防止两个并发访问。为了保护更多,你可以做类似 sleep 0.$(printf "%02d" $((RANDOM / 10))) 的事情——让睡眠时间随机,这样他们就可以少创建一个文件 "concurently".

另外,为了以防万一,我不会镜像到 httpdocs 目录,而是镜像到一些临时目录,例如 tmp=httpdocs_$(uuidgen); lftp "mirror .. $tmp",以后可以重命名为 lftp 'rmdir httpdocs; rename $tmp httpdocs",以便使部署更安全更少的停机时间(更少的时间 httpdocs beeing empty)。对于未来,我建议只移动到支持文件锁定的 safer/more 连接远程服务器的高级协议。像 ssh。或者桑巴。