docker - Jenkins cleanWs 由于权限不清理文件
问题描述
我们使用 Jenkins(除其他外)运行一系列测试作业。对于每个测试,从 Nexus 存储库下载必要的 docker 图像和其他对象。所需的容器和服务是使用 docker-compose 和 maven 构建和执行的。这一切正常,测试按需要运行。
测试后,应清理工作区文件和目录。cleanWs
使用插件应该可以做到这一点。但是,默认情况下,这会使用该deferredWipeout
选项,这会导致存储库目录的整个副本留在工作区中名为<test-name>-ws-cleanup-<run-ID>
. 这些通过将@2、@3 等添加到测试名称而随着时间累积。从逻辑上讲,我添加了选项deleteDirs: true
和disableDeferredWipeout: true
. 这会产生如下错误:
hudson.AbortException: Cannot delete workspace: Unable to delete '/data/jenkins/workspace/XXXX-batch@2/XXX-batch-ant-core/target/classes/de/ubs/XXX/batch/ant/core/AbstractLicenseCheck.class'. Tried 3 times (of a maximum of 3) waiting 0.1 sec between attempts.
发生这种情况是因为,出于我不完全清楚的原因,创建的某些子目录和文件的所有者“root”具有权限设置为 755(即 rwxr-xr-x)。这些通常是 maven 构建创建的目标目录,但我不确定是否没有其他目录。涉及数千个文件,所以我还没有检查它们……还没有。我可能最终不得不这样做。
为了解决这个问题,清理服务定义被添加到定义构建测试服务的 docker-compose.yml文件中。测试了以下命令:
command: rm -rf * && rm -rf /opt/test/*
这导致了关于 rm 命令的无效选项“c”的模糊错误消息。(??) 否则无效。在检查了其他一些堆栈溢出问题后,我尝试了这个:
command: sh -c "rm -rf * && rm -rf /opt/test/*"
这不会产生错误,但也不会产生预期的效果。使用收益率--verbose
选项docker-compose run
:
2021-03-09 08:29:26 compose.cli.verbose_proxy.proxy_callable: docker inspect_container -> {'AppArmorProfile': '',
2021-03-09 08:29:26 'Args': ['rm', '-rf', '*', '&&', 'rm', '-rf', '/opt/test/*'],
2021-03-09 08:29:26 'Config': {'AttachStderr': True,
2021-03-09 08:29:26 'AttachStdin': True,
2021-03-09 08:29:26 'AttachStdout': True,
2021-03-09 08:29:26 'Cmd': ['rm', '-rf', '*', '&&', 'rm', '-rf', '/opt/test/*'],
2021-03-09 08:29:26 'Domainname': '',
2021-03-09 08:29:26 'Entrypoint': ['/usr/local/bin/mvn-entrypoint.sh'],
2021-03-09 08:29:26 'Env': ['TZ=Europe/Berlin',
2021-03-09 08:29:26 'CONTAINERED=true',
2021-03-09 08:29:26 ...
坦率地说,这并没有告诉我该命令以某种方式被识别。
另一种方法是尝试将文件和目录的权限更改为 777:
command: echo "<password>" | su -c "chmod -R 777 ."
这在控制台上执行时有效,但在docker-compose.yml或 Jenkins 使用的管道 groovy 脚本中使用时无效。
我不知道我还能尝试什么,如果有任何提示,我将不胜感激。如果需要,我很乐意提供更多详细信息。
解决方案
这个问题实际上是一个复合问题。
首先,不能按照 Nisarg Shah 的建议更改所有者和组,因为在容器内没有名为 Jenkins 的用户。
777
最终的解决方案是通过以root身份发出命令,将测试中文件的权限设置为(即rwxrwxrwx)。最后 docker-compose.yml 中的命令如下所示:
command: sh -c 'echo "<root-password>" | su root -c "chmod -R 777 ."'
要达到这个阶段需要大量的实验,因为命令由不同的进程解析,包括 docker-compose 和 shell。
如果您没有使用 docker-compose 并且希望在 groovy 管道脚本中做同样的事情,那么以下应该可以工作(它在众多实验之一中为我做了):
sh 'echo "<root-password>" | su root -c "chmod -R 777 ."'
使用上述任何一种方法,并通过在 groovy 管道脚本中添加以下阶段,Jenkins 能够执行所需的清理:
stage('cleanup') {
cleanWs deleteDirs: true, disableDeferredWipeout: true
}
希望这可以帮助有类似问题的人。
PS 在我们的系统上,jenkins 不在 sudoer 组中。因此使用“su root”。如果您的 jenkins 是 sudoer,那么 sudo 当然也可以解决问题。
推荐阅读
- python - 如何在 python 中计算数据框中每个唯一原始变量的总和?
- scala - 如何找到最小值并用相应的列显示它
- javascript - JSON 的属性
- c++ - vs code microsoft c/c++ 扩展不会自动关闭“<”inlude 标头中的括号
- jquery - 格式化 DataTables 中的数据时“data.replace 不是函数”
- python - @class 方法、@static 方法和普通函数有什么区别以及如何使用它们
- google-cloud-dataprep - 如何取消正在运行的作业(出现问题)?
- three.js - 在 Three.js 中使用旋转父对象旋转 3D 对象以面对给定方向时出现问题
- python - Spark - 如何识别和删除空行
- java - JHipster 实体在 JSON 中序列化时将用户属性设置为 null