Windows Batch脚本报错:) was unexpected at this time(退出码255)
Jenkins IMPI部署脚本报错排查:
) was unexpected at this time 问题背景
接手Jenkins上的IMPI部署脚本,原脚本将Jenkins凭证写入明文文件后传给mpiexec。为验证功能,修改为直接向mpiexec传入明文凭证,执行时出现) was unexpected at this time错误,脚本返回退出码255。
报错日志
ccr\******* c:\iusers\jenkins\workspace\impi_PR-3056_qy6gczv2>mpiexec -register -username CCR\****** -password **** [2022-09-22T18:39:50.318Z] credentials were saved. [2022-09-22T18:39:50.318Z] ) was unexpected at this time. [2022-09-22T18:39:50.318Z] ccr\********c:\iusers\jenkins\workspace\impi_PR-3056_qy6gczv2>) else if /i "ONEAPI" equ "PSXE" ( script returned exit code 255
相关Groovy代码
package impi import infra.util.* public class Deploy { final private def script final private String artifactsDir final private def params final private String siteId public Deploy(final def script, final String artifactsDir, final def params, final String siteId) { this.script = script this.artifactsDir = artifactsDir this.params = params this.siteId = siteId } public void deployLinux() { script.withEnv([ "PACKAGE_INSTALL_LAYOUT=${params.PACKAGE_INSTALL_LAYOUT ?: 'ONEAPI'}", "artifacts_dir=${artifactsDir}", "ONEAPI_GLOB=${Consts.OS_CUSTOMIZED_VARS.linux.oneapiPackageMask}", "PSXE_GLOB=${Consts.OS_CUSTOMIZED_VARS.linux.psxePackageMask}" ]) { script.sh('''#!/bin/bash set -ex -o pipefail # Package specifications ONEAPI_DIR_NAME="oneapi_impi" PSXE_DIR_NAME="psxe_impi" ### PACKAGE_INSTALL_LAYOUT=${PACKAGE_INSTALL_LAYOUT:-ONEAPI} echo "DEBUG: Install package for ${PACKAGE_INSTALL_LAYOUT} configuration" selector_glob="${PACKAGE_INSTALL_LAYOUT}_GLOB" selector_dirname="${PACKAGE_INSTALL_LAYOUT}_DIR_NAME" package_path=$( ls -1 $artifacts_dir/${!selector_glob} ) package_target_dir_name=${!selector_dirname} tar xfz $package_path pushd $( basename $package_path .tgz ) > /dev/null unzip -P accept package.zip ./install.sh -s -d $artifacts_dir/$package_target_dir_name echo "DEBUG: Package in ${PACKAGE_INSTALL_LAYOUT} configuration successfully installed to $artifacts_dir/$package_target_dir_name dir" popd > /dev/null echo "DEBUG: Enable ${PACKAGE_INSTALL_LAYOUT} testing layout" ln -s $artifacts_dir/$package_target_dir_name $artifacts_dir/impi ''') } } public void deployWindows() { script.withEnv([ "ARTIFACTS_DIR=${Utils.getWindowsPath(script, artifactsDir, "^/p/", BaseConsts.CIFS_SERVER_v0[siteId])}", // Autogen archive is always here """MPI_ARCHIVE_PATH=${params.MPI_ARCHIVE_PATH ? Utils.getWindowsPath(script, params.MPI_ARCHIVE_PATH, "^/p/", BaseConsts.CIFS_SERVER_v0[siteId]) : Utils.getWindowsPath(script, artifactsDir, '^/p/', BaseConsts.CIFS_SERVER_v0[siteId])}""", "PSXE_PACKAGE_MASK=${Consts.OS_CUSTOMIZED_VARS.windows.psxePackageMask}", "ONEAPI_PACKAGE_MASK=${Consts.OS_CUSTOMIZED_VARS.windows.oneapiPackageMask}", "TOOLS_DIR=${Utils.getWindowsPath(script, BaseConsts.CIFS_TOOLS_DIR_v0, "^/p/", BaseConsts.CIFS_SERVER_v0[siteId])}", "CYGWIN_DIR=${BaseConsts.CYGWIN_DIR}", "SRC_DIR=${Consts.WINDOWS_SRC_DIR}", "PACKAGE_INSTALL_LAYOUT=${params.PACKAGE_INSTALL_LAYOUT ?: 'ONEAPI'}" ]) { script.withCredentials([script.usernamePassword(credentialsId: 'ec25177f-b239-43cb-a2d5-874a88f97fc9', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) { script.bat(''' PATH=%TOOLS_DIR%\\\\unzip-5.51-1-bin\\\\bin;%CYGWIN_DIR%\\\\bin;%PATH% REM Create a source dir in local workspace if exist %SRC_DIR% rmdir /s/q %SRC_DIR% if %errorlevel% neq 0 exit /b %errorlevel% mkdir %SRC_DIR% REM Obtain IMPI sources with autogen results copy %MPI_ARCHIVE_PATH%\\\\impi_src.tgz . copy %ARTIFACTS_DIR%\\\\workspace-1-autogen.tgz . tar -xzf impi_src.tgz -C %SRC_DIR% if %errorlevel% neq 0 exit /b %errorlevel% tar -xzf workspace-1-autogen.tgz -C %SRC_DIR% icacls %SRC_DIR% /remove sys_ctlab icacls %SRC_DIR% /Q /grant sys_ctlab:(OI)(CI)F /T icacls %SRC_DIR% echo "INFO: Deploy %PACKAGE_INSTALL_LAYOUT% package layout" REM (echo CCR\\\\%USERNAME%& echo %PASSWORD%& echo %PASSWORD%) > auth_data.txt mpiexec -register -username CCR\\\\****** -password **** REM Obtain IMPI packages and configure services if /i "%PACKAGE_INSTALL_LAYOUT%" equ "ONEAPI" ( copy %MPI_ARCHIVE_PATH%\\\\%ONEAPI_PACKAGE_MASK% . unzip -o -P"accept" %ONEAPI_PACKAGE_MASK% if %errorlevel% neq 0 exit /b %errorlevel% bin\\\\hydra_service.exe -install if %errorlevel% neq 0 exit /b %errorlevel% env\\\\vars.bat if %errorlevel% neq 0 exit /b %errorlevel% REM TODO: Fix the mpiexec register call w/ credentials REM type auth_data.txt | mpiexec -register REM if %errorlevel% neq 0 exit /b %errorlevel% ) else if /i "%PACKAGE_INSTALL_LAYOUT%" equ "PSXE" ( copy %MPI_ARCHIVE_PATH%\\\\%PSXE_PACKAGE_MASK% . unzip -o -P"accept" %PSXE_PACKAGE_MASK% if %errorlevel% neq 0 exit /b %errorlevel% intel64\\\\bin\\\\hydra_service.exe -install if %errorlevel% neq 0 exit /b %errorlevel% intel64\\\\bin\\\\mpivars.bat if %errorlevel% neq 0 exit /b %errorlevel% REM TODO: Fix the mpiexec register call w/ credentials REM type auth_data.txt | mpiexec -register REM if %errorlevel% neq 0 exit /b %errorlevel% ) else ( echo "ERROR: PACKAGE_INSTALL_LAYOUT=%PACKAGE_INSTALL_LAYOUT% is not correct! Please use PSXE or ONEAPI." exit /b 1 ) del auth_data.txt '''.stripIndent()) } } } public void uninstallWindows() { script.withEnv([ "PACKAGE_INSTALL_LAYOUT=${params.PACKAGE_INSTALL_LAYOUT ?: 'ONEAPI'}" ]) { script.bat(''' if /i "%PACKAGE_INSTALL_LAYOUT%" equ "ONEAPI" ( if exist "bin\\\\hydra_service.exe" bin\\\\hydra_service.exe -remove if %errorlevel% neq 0 exit /b %errorlevel% rem rmdir /s /q "bin" rem if %errorlevel% neq 0 exit /b %errorlevel% ) else if /i "%PACKAGE_INSTALL_LAYOUT%" equ "PSXE" ( if exist "intel64\\\\bin\\\\hydra_service.exe" intel64\\\\bin\\\\hydra_service.exe -remove if %errorlevel% neq 0 exit /b %errorlevel% rem rmdir /s /q "intel64\\\\bin" rem if %errorlevel% neq 0 exit /b %errorlevel% ) else ( echo "ERROR: PACKAGE_INSTALL_LAYOUT=%PACKAGE_INSTALL_LAYOUT% is not correct! Please use PSXE or ONEAPI." ) '''.stripIndent()) } } }
问题排查与解决方法
核心原因分析
从报错日志和代码来看,触发错误的核心原因有两个:
- 批处理调用外部脚本未加
call:如果mpiexec是.bat/.cmd批处理文件而非可执行程序,直接执行会夺走当前批处理的控制权,后续代码会被当作独立命令执行,导致else if的)被单独解析,引发语法错误。 - 密码含特殊字符破坏批处理语法:如果密码包含
&、(、)、!等批处理特殊字符,直接传入会被解析为命令的一部分,打乱后续代码结构。
针对性修复方案
方案1:添加call命令调用mpiexec
修改deployWindows方法中的mpiexec调用行,添加call确保当前批处理能继续执行后续代码,同时用引号包裹参数避免分割错误:
call mpiexec -register -username "CCR\\%USERNAME%" -password "%PASSWORD%"
方案2:恢复文件传递凭证的方式(更稳妥)
如果密码存在特殊字符,建议回到原方案,通过文件传递凭证,既避免直接暴露凭证,又规避语法问题:
REM 恢复凭证写入文件的逻辑 (echo CCR\\%USERNAME%& echo %PASSWORD%& echo %PASSWORD%) > auth_data.txt type auth_data.txt | call mpiexec -register
执行完成后保留原代码中的del auth_data.txt步骤,清理临时文件。
方案3:处理特殊字符(若必须直接传参)
如果坚持直接传参,启用延迟变量扩展来处理特殊字符:
在批处理开头添加setlocal enabledelayedexpansion,然后用!PASSWORD!代替%PASSWORD%:
setlocal enabledelayedexpansion call mpiexec -register -username "CCR\\!USERNAME!" -password "!PASSWORD!" endlocal
内容的提问来源于stack exchange,提问作者Dvsmp
相关产品推荐
相关产品推荐

