Jenkins 作业因命令中的 for 循环而失败

Posted

技术标签:

【中文标题】Jenkins 作业因命令中的 for 循环而失败【英文标题】:Jenkins job is failing with for loop in command 【发布时间】:2020-10-20 22:40:21 【问题描述】:

在 Jenkins 中,我尝试在 BAT 文件中实现的命令很少。所以我有 2 个 BAT 文件(RUN.BAT 和 CHANGE.BAT)。在RUN.BAT中,命令如下:

CD\
E:
CD E:\RESULTS\1
mkdir 1
xcopy E:\I1\0 E:\RESULTS\1

Above Given Command 将转到特定文件夹并创建一个名为“1”的文件夹,然后 XCOPY 行会将内容从文件夹“O”复制到文件夹“1”。

现在让我们来看看 CHANGE.BAT,这里的命令是:

for /f "tokens=1-7 delims=-:. " %%a in ("%date% %time%") do ren E:\RESULTS\1 %%a%%b%%c_%%d%%e%%f%%g

此命令会将文件夹名称更改为当前系统的日期和时间。

这就是问题所在,当我在 CMD 上调用上述 bat 文件时,它们运行得非常好。但同样不适用于 JENKINS 并抛出“命令的语法不正确”。

我无法理解的是,.bat 文件在 CMD 中有效,但在 Jenkins 中同样无效。

请指导我。

【问题讨论】:

您的意思是 Jenkins 正在生成该错误(并且可能没有启动批处理文件),还是批处理文件中的某些内容产生了错误?如果是后者,是哪一个? RUN.BATCHANGE.BAT。如果您不知道是否正在调用其中任何一个,请将 echo Start of RUN > "%TEMP%\RUN.LOG" 之类的行添加到每个批处理文件中(第二次将 RUN 更改为 CHANGE)。如果/一旦您知道正在调用批处理文件,请添加额外的行,例如echo Got to XXX >> "%TEMP%\RUN.LOG",以查看失败的地方(不是此版本中的两个 >>)。 另外,顺便说一句,第一个文件的前三行可能可以替换为CD /D E:\RESULTS(参见CD/?)。你的意思是在(可能已经存在的)1 目录内部创建一个1 目录吗? 【参考方案1】:

RUN.BATCHANGE.BAT 这两个批处理文件可以用一个命令行替换为一个批处理文件:

@for /F "tokens=1-6 delims=/: " %%I in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do @%SystemRoot%\System32\robocopy.exe "E:\I1\0" "E:\RESULTS\%%I-%%J-%%K_%%L%%M%%N" /E /R:3 /W:2 /NDL /NFL /NJH /NJS & goto :EOF

ROBOCOPYXCOPY 的替代品,自 Windows Vista 和 Windows Server 2003 起默认可用。

首先使用无效的源目录路径执行 ROBOCOPY 以获取由 ROBOCOPY 输出的错误消息,其中包含区域独立格式的当前日期和时间。区域无关格式意味着日期和时间的格式不依赖于为使用的帐户配置的国家/地区,该帐户用于 Jenkins 作为服务运行的内置本地系统帐户。这很可能是命令 REN 输出错误消息的原因。与使用用户帐户执行批处理文件相比,使用系统帐户设置执行批处理文件时的新文件夹名称不同。

然后 ROBOCOPY 再次运行,使用正确的源目录路径和目标目录路径,yyyy-MM-dd_hhmmss 作为 E:\RESULTS 中的目录名称。

如果目标目录不存在,

ROBOCOPY 会像 XCOPY 一样自动创建整个目录树到目标目录。

命令goto :EOF 需要在复制文件后结束批处理文件执行,因为ROBOCOPY 输出第二行错误,否则FOR也会处理>。如果有更多行要执行,则可以将预定义标签 :EOF 替换为写在下一行的任何其他标签:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "tokens=1-6 delims=/: " %%I in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do %SystemRoot%\System32\robocopy.exe "E:\I1\0" "E:\RESULTS\%%I-%%J-%%K_%%L%%M%%N" /E /R:3 /W:2 /NDL /NFL /NJH /NJS & goto FilesCopied
:FilesCopied
rem More command lines to execute.
endlocal

为了完整起见,解决方案也适用于 Windows XP 和所有更高版本的 Windows:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "CurrentDateTime=%%I"
set "CurrentDateTime=%CurrentDateTime:~0,4%-%CurrentDateTime:~4,2%-%CurrentDateTime:~6,2%_%CurrentDateTime:~8,6%"
%SystemRoot%\System32\xcopy.exe "E:\I1\0" "E:\RESULTS\%CurrentDateTime%\" /I /R /Q /Y >nul
endlocal

有关 ROBOCOPY 在使用无效的源目录路径首先运行它时输出什么以及 FOR 如何处理此输出的完整说明,请参阅Time is set incorrectly after midnight。 WMIC 的 Windows XP 解决方案在同一个答案中进行了详细说明。

要了解所使用的命令及其工作原理,请打开command prompt 窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

echo /? endlocal /? for /? goto /? if /? robocopy /? set /? setlocal /? wmic /? wmic os /? wmic os get /? wmic os get localdatetime /? xcopy /?

【讨论】:

非常感谢@Mofi 这个解决方案的帮助,它成功地重命名了文件夹并将文件的内容从一个地方复制到另一个地方。

以上是关于Jenkins 作业因命令中的 for 循环而失败的主要内容,如果未能解决你的问题,请参考以下文章

Jenkins 可以为同一个 Maven 作业支持 2 个 Java 版本吗?

Glue 作业因 Amazon S3 超时而失败

Jenkins iOS 作业中断,因为“致命:日志语句不同步:当前测试用例为空”

即使 ROBOCOPY 命令在 BAT 脚本中成功执行,JENKINS 作业也会失败

Spark Kafka Streaming 作业因 InvalidClassException 而失败

Big Query 作业因“遇到错误字符 (ASCII 0)”而失败。