Jenkins升级后Pipeline内的sshCommand报错

文章讲述了在将Jenkins从2.401.3升级到2.428时,由于JSch插件升级导致Pipeline无法执行的问题,原因是服务端算法过时。提供了解决方案,即通过修改Jenkins启动命令添加系统属性来支持旧版本服务器的ssh-rsa算法。

现象

最近把Jenkins从2.401.3升级至2.428后(严格来说,是JSch插件从0.1.x升级到了0.2.x后),原先能正常工作的部分Pipeline无法执行,报错信息为:

com.jcraft.jsch.JSchAlgoNegoFailException: Algorithm negotiation fail: algorithmName="server_host_key" jschProposal="ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256" serverProposal="ssh-rsa,ssh-dss"

原因分析

错误信息的大意是客户端和服务端使用的算法无法兼容,其中 jschProposal 是我们的Jenkins SSH插件启用的算法列表,而 serverProposal 是服务端支持的算法列表。

出现这种情况,多半是ssh服务端版本太低,算法过时(比如 CentOS / RedHat 6 自带的 sshd),而新版本的Jenkins的 JSch dependency plugin 0.2.x 默认禁用了这些算法,参考 JSch v0.2.0 的 Release:Release v0.2.0 · mwiede/jsch (github.com)icon-default.png?t=N7T8https://github.com/mwiede/jsch/releases/tag/jsch-0.2.0

解决

JSch官方也提出了几个兼容老系统的方案,参考:mwiede/jsch: fork of the popular jsch library (github.com)icon-default.png?t=N7T8https://github.com/mwiede/jsch#why-do-ssh-rsa-type-keys-not-work-with-this-jsch-fork-and-my-server

这里放一个验证过可行的方案,就是让 JSch 支持 ssh-rsa(ssh-dss同理):

修改jenkins启动命令,添加系统属性 -Djsch.client_pubkey 和 -Djsch.server_host_key,JSch运行时会读取该属性,覆盖默认配置。

这两个属性的值实际上就是把报错信息里的 jschProposal 拿过来,在后面追加一个 ssh-rsa。

java -jar \
-Djsch.client_pubkey=ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256,ssh-rsa \
-Djsch.server_host_key=ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256,ssh-rsa \
jenkins-2.428.war --prefix=/jenkins

结语

这次发生问题的Jenkins插件版本比较新,还算热乎,暂时也没有搜到相关中文资料,所以分享出来。

也试过官方提到的其他方案,比如调整Jenkins所在服务器的 /etc/ssh/ssh_config~/.ssh/config 等配置文件,根本没有效果,可能是因为Jenkins里的JSch是经过 SSH Pipeline Steps 插件封装调用的,没有读取这些配置(当然也不排除是我调整的姿势不对)。

Started by user admin [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/model_lora [Pipeline] { [Pipeline] withCredentials Masking supported pattern matches of $GITLAB_TOKEN [Pipeline] { [Pipeline] withEnv [Pipeline] { [Pipeline] stage [Pipeline] { (🔍 参数校验) [Pipeline] script [Pipeline] { [Pipeline] echo [INFO] 校验输入参数... [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (📁 创建远程工作目录) [Pipeline] script [Pipeline] { [Pipeline] sshCommand Executing command on target[10.100.15.95]: #!/bin/bash set -eo pipefail rm -rf '/opt/tmp/lora/20250918_173956' mkdir -p '/opt/tmp/lora/20250918_173956/model' \ '/opt/tmp/lora/20250918_173956/dataset' \ '/opt/tmp/lora/20250918_173956/model_lora' echo -e "\033[1;32m✅ 工作目录已创建:/opt/tmp/lora/20250918_173956\033[0m" sudo: false ✅ 工作目录已创建:/opt/tmp/lora/20250918_173956 [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (📥 克隆模型仓库 (main 分支)) [Pipeline] script [Pipeline] { [Pipeline] withCredentials Masking supported pattern matches of $GITLAB_TOKEN_VALUE [Pipeline] { [Pipeline] echo [INFO] 克隆模型仓库(仅 main 分支):models/qwen-VL -> /opt/tmp/lora/20250918_173956/model [Pipeline] sshCommand Warning: A secret was passed to "sshCommand" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [GITLAB_TOKEN, GITLAB_TOKEN_VALUE] See https://jenkins.io/redirect/groovy-string-interpolation for details. Executing command on target[10.100.15.95]: #!/bin/bash set -eo pipefail set -x cd '/opt/tmp/lora/20250918_173956/model' rm -rf ./* .git* git clone -b main --depth 1 'http://root:****@10.100.15.95:8181/models/qwen-VL.git' . git config user.email "jenkins@auto.dev" git config user.name "Jenkins CI Bot" # 可选:检查关键模型文件(如 config.json) if [ ! -f ./config.json ] && [ ! -f ./model_index.json ]; then echo -e "\033[1;33m⚠️ 注意:未发现标准模型配置文件\033[0m" fi echo -e "\033[1;32m✅ 模型文件克隆完成\033[0m" sudo: false + cd /opt/tmp/lora/20250918_173956/model + rm -rf './*' '.git*' + git clone -b main --depth 1 http://root:****@10.100.15.95:8181/models/qwen-VL.git . Cloning into '.'... Updating files: 71% (15/21) Updating files: 76% (16/21) Updating files: 80% (17/21) Updating files: 85% (18/21) Updating files: 90% (19/21) Updating files: 95% (20/21) Updating files: 100% (21/21) Updating files: 100% (21/21), done. + git config user.email jenkins@auto.dev + git config user.name 'Jenkins CI Bot' + '[' '!' -f ./config.json ']' + echo -e '\033[1;32m✅ 模型文件克隆完成\033[0m' ✅ 模型文件克隆完成 [Pipeline] } [Pipeline] // withCredentials [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (📥 克隆数据集仓库 (main 分支)) [Pipeline] script [Pipeline] { [Pipeline] withCredentials Masking supported pattern matches of $GITLAB_TOKEN_VALUE [Pipeline] { [Pipeline] echo [INFO] 克隆数据集仓库(仅 main 分支):datasets/test_lora -> /opt/tmp/lora/20250918_173956/dataset [Pipeline] sshCommand Warning: A secret was passed to "sshCommand" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [GITLAB_TOKEN, GITLAB_TOKEN_VALUE] See https://jenkins.io/redirect/groovy-string-interpolation for details. Executing command on target[10.100.15.95]: #!/bin/bash set -eo pipefail set -x cd '/opt/tmp/lora/20250918_173956/dataset' rm -rf ./* .git* git clone -b main --depth 1 'http://root:****@10.100.15.95:8181/datasets/test_lora.git' . git config user.email "jenkins@auto.dev" git config user.name "Jenkins CI Bot" # ✅ 关键修复:使用相对路径检查文件是否存在 if [ ! -f ./train.jsonl ]; then echo -e "\033[1;31m❌ 错误:数据集文件 ./train.jsonl 不存在,请确认仓库中包含该文件\033[0m" exit 1 fi echo -e "\033[1;32m✅ 数据集文件克隆完成\033[0m" sudo: false + cd /opt/tmp/lora/20250918_173956/dataset + rm -rf './*' '.git*' + git clone -b main --depth 1 http://root:****@10.100.15.95:8181/datasets/test_lora.git . Cloning into '.'... + git config user.email jenkins@auto.dev + git config user.name 'Jenkins CI Bot' + '[' '!' -f ./train.jsonl ']' + echo -e '\033[1;32m✅ 数据集文件克隆完成\033[0m' ✅ 数据集文件克隆完成 [Pipeline] } [Pipeline] // withCredentials [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (🚀 执行微调命令) [Pipeline] script [Pipeline] { [Pipeline] echo [INFO] 原始命令: CUDA_VISIBLE_DEVICES=显卡 swift sft --torch_dtype 'bfloat16' --model '模型地址' --dataset '数据集地址' --split_dataset_ratio '0.2' --max_length '2048' --use_galore 'True' --galore_rank '64' --task_type 'causal_lm' --per_device_train_batch_size '14' --per_device_eval_batch_size '28' --learning_rate '1e-4' --num_train_epochs '2' --gradient_accumulation_steps '4' --eval_steps '500' --output_dir '模型保存地址' --neftune_noise_alpha '0' --report_to 'tensorboard' --add_version False [Pipeline] echo [DEBUG] 最终执行命令: CUDA_VISIBLE_DEVICES=7 [Pipeline] sshCommand Executing command on target[10.100.15.95]: #!/bin/bash set -eo pipefail set -x export CUDA_VISIBLE_DEVICES=7 cd '/opt/tmp/lora/20250918_173956' source '/root/anaconda3/etc/profile.d/conda.sh' || true conda activate 'swift' || { echo 'Failed to activate conda env'; exit 1; } CUDA_VISIBLE_DEVICES=7 echo -e "\033[1;32m✅ 微调任务执行成功!\033[0m" sudo: false + export CUDA_VISIBLE_DEVICES=7 + CUDA_VISIBLE_DEVICES=7 + cd /opt/tmp/lora/20250918_173956 + source /root/anaconda3/etc/profile.d/conda.sh ++ _CONDA_EXE=/root/anaconda3/bin/conda ++ _CONDA_ROOT=/root/anaconda3 ++ _conda_set_vars ++ '[' -n x ']' ++ _CONDA_SHELL_FLAVOR=bash ++ '[' -z x ']' ++ '[' -z x ']' ++ '[' -z x ']' + conda activate swift + '[' 2 -lt 1 ']' + local cmd=activate + shift + case "$cmd" in + _conda_activate swift + '[' -n '' ']' + local ask_conda ++ PS1='[\[\033[01;31m\]\u\[\033[00m\]@\[\033[01;32m\]\h\[\e[0m\](\[\e[01;33m\]15.95\[\e[0m\]) \[\033[01;34m\]\W\[\e[0m\]]# ' ++ /root/anaconda3/bin/conda shell.posix activate swift + ask_conda='PS1='\''(swift) [\[\033[01;31m\]\u\[\033[00m\]@\[\033[01;32m\]\h\[\e[0m\](\[\e[01;33m\]15.95\[\e[0m\]) \[\033[01;34m\]\W\[\e[0m\]]# '\'' \export CONDA_DEFAULT_ENV='\''swift'\'' \export CONDA_PREFIX='\''/opt/tpapp/conda/envs/swift'\'' \export CONDA_PREFIX_1='\''/root/anaconda3'\'' \export CONDA_PROMPT_MODIFIER='\''(swift) '\'' \export CONDA_SHLVL='\''2'\'' \export PATH='\''/opt/tpapp/conda/envs/swift/bin:/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'\''' + eval 'PS1='\''(swift) [\[\033[01;31m\]\u\[\033[00m\]@\[\033[01;32m\]\h\[\e[0m\](\[\e[01;33m\]15.95\[\e[0m\]) \[\033[01;34m\]\W\[\e[0m\]]# '\'' \export CONDA_DEFAULT_ENV='\''swift'\'' \export CONDA_PREFIX='\''/opt/tpapp/conda/envs/swift'\'' \export CONDA_PREFIX_1='\''/root/anaconda3'\'' ✅ 微调任务执行成功! \export CONDA_PROMPT_MODIFIER='\''(swift) '\'' \export CONDA_SHLVL='\''2'\'' \export PATH='\''/opt/tpapp/conda/envs/swift/bin:/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'\''' ++ PS1='(swift) [\[\033[01;31m\]\u\[\033[00m\]@\[\033[01;32m\]\h\[\e[0m\](\[\e[01;33m\]15.95\[\e[0m\]) \[\033[01;34m\]\W\[\e[0m\]]# ' ++ export CONDA_DEFAULT_ENV=swift ++ CONDA_DEFAULT_ENV=swift ++ export CONDA_PREFIX=/opt/tpapp/conda/envs/swift ++ CONDA_PREFIX=/opt/tpapp/conda/envs/swift ++ export CONDA_PREFIX_1=/root/anaconda3 ++ CONDA_PREFIX_1=/root/anaconda3 ++ export 'CONDA_PROMPT_MODIFIER=(swift) ' ++ CONDA_PROMPT_MODIFIER='(swift) ' ++ export CONDA_SHLVL=2 ++ CONDA_SHLVL=2 ++ export PATH=/opt/tpapp/conda/envs/swift/bin:/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ++ PATH=/opt/tpapp/conda/envs/swift/bin:/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + _conda_hashr + case "$_CONDA_SHELL_FLAVOR" in + hash -r + CUDA_VISIBLE_DEVICES=7 + echo -e '\033[1;32m✅ 微调任务执行成功!\033[0m' [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (📤 上传结果到 GitLab) [Pipeline] script [Pipeline] { [Pipeline] withCredentials Masking supported pattern matches of $GITLAB_TOKEN_VALUE [Pipeline] { [Pipeline] sshCommand Warning: A secret was passed to "sshCommand" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [GITLAB_TOKEN, GITLAB_TOKEN_VALUE] See https://jenkins.io/redirect/groovy-string-interpolation for details. Executing command on target[10.100.15.95]: #!/bin/bash set -eo pipefail set -x OUTPUT_REPO="${params.OUTPUT_REPO}" REPO_URL="http://root:****@10.100.15.95:8181/lora/qwen-VL.git" LOCAL_OUTPUT="/opt/tmp/lora/20250918_173956/model_lora" TMP_CLONE="/tmp/git-upload/$OUTPUT_REPO" mkdir -p "$(dirname "$TMP_CLONE")" rm -rf "$TMP_CLONE" mkdir -p "$TMP_CLONE" cd "$TMP_CLONE" git init git config user.email "jenkins@auto.dev" git config user.name "Jenkins CI Bot" if [ -d "$LOCAL_OUTPUT" ] && [ -n "$(ls -A $LOCAL_OUTPUT)" ]; then cp -r "$LOCAL_OUTPUT"/* ./ else echo "⚠️ 输出目录为空或不存在" touch EMPTY_OUTPUT_PLACEHOLDER.txt fi if [ -z "$(ls -A .)" ]; then echo "🚫 无任何内容可提交" exit 0 fi git add . git commit -m "chore: upload fine-tuned output [ci skip]" || exit 0 encode_url() { python3 -c "import urllib.parse; print(urllib.parse.quote('$1', safe=''))" } GROUP=$(echo "$OUTPUT_REPO" | cut -d'/' -f1) PROJECT=$(echo "$OUTPUT_REPO" | cut -d'/' -f2) ENCODED_REPO=$(encode_url "$OUTPUT_REPO") STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/projects/$ENCODED_REPO") if [ "$STATUS_CODE" -ne 200 ]; then echo "🔧 仓库不存在,正在创建..." ENCODED_GROUP=$(encode_url "$GROUP") GROUP_ID=$(curl -s -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/groups/$ENCODED_GROUP" | jq -r '.id') if [ "$GROUP_ID" == "null" ]; then echo "❌ 无法获取 Group ID,请确认 '$GROUP' 存在" exit 1 fi curl -X POST \ -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/projects" \ -d "name=$PROJECT&namespace_id=$GROUP_ID&description=Auto-created+for+LoRA+fine-tuning" \ || { echo "❌ 创建项目失败"; exit 1; } fi git remote add origin "$REPO_URL" || git remote set-url origin "$REPO_URL" git push -u origin main --force echo -e "\033[1;32m🎉 成功上传至 GitLab:$REPO_URL\033[0m" sudo: false bash: line 5: ${params.OUTPUT_REPO}: bad substitution Failed command target#185 with status 1: #!/bin/bash set -eo pipefail set -x OUTPUT_REPO="${params.OUTPUT_REPO}" REPO_URL="http://root:****@10.100.15.95:8181/lora/qwen-VL.git" LOCAL_OUTPUT="/opt/tmp/lora/20250918_173956/model_lora" TMP_CLONE="/tmp/git-upload/$OUTPUT_REPO" mkdir -p "$(dirname "$TMP_CLONE")" rm -rf "$TMP_CLONE" mkdir -p "$TMP_CLONE" cd "$TMP_CLONE" git init git config user.email "jenkins@auto.dev" git config user.name "Jenkins CI Bot" if [ -d "$LOCAL_OUTPUT" ] && [ -n "$(ls -A $LOCAL_OUTPUT)" ]; then cp -r "$LOCAL_OUTPUT"/* ./ else echo "⚠️ 输出目录为空或不存在" touch EMPTY_OUTPUT_PLACEHOLDER.txt fi if [ -z "$(ls -A .)" ]; then echo "🚫 无任何内容可提交" exit 0 fi git add . git commit -m "chore: upload fine-tuned output [ci skip]" || exit 0 encode_url() { python3 -c "import urllib.parse; print(urllib.parse.quote('$1', safe=''))" } GROUP=$(echo "$OUTPUT_REPO" | cut -d'/' -f1) PROJECT=$(echo "$OUTPUT_REPO" | cut -d'/' -f2) ENCODED_REPO=$(encode_url "$OUTPUT_REPO") STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/projects/$ENCODED_REPO") if [ "$STATUS_CODE" -ne 200 ]; then echo "🔧 仓库不存在,正在创建..." ENCODED_GROUP=$(encode_url "$GROUP") GROUP_ID=$(curl -s -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/groups/$ENCODED_GROUP" | jq -r '.id') if [ "$GROUP_ID" == "null" ]; then echo "❌ 无法获取 Group ID,请确认 '$GROUP' 存在" exit 1 fi curl -X POST \ -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/projects" \ -d "name=$PROJECT&namespace_id=$GROUP_ID&description=Auto-created+for+LoRA+fine-tuning" \ || { echo "❌ 创建项目失败"; exit 1; } fi git remote add origin "$REPO_URL" || git remote set-url origin "$REPO_URL" git push -u origin main --force echo -e "\033[1;32m🎉 成功上传至 GitLab:$REPO_URL\033[0m" [Pipeline] } [Pipeline] // withCredentials [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Declarative: Post Actions) [Pipeline] cleanWs [WS-CLEANUP] Deleting project workspace... [WS-CLEANUP] Deferred wipeout is used... [WS-CLEANUP] done [Pipeline] echo ❌ 流水线执行失败,请检查日志。 [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // withEnv [Pipeline] } [Pipeline] // withCredentials [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Also: org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: ff974788-02c3-4cfd-a6ab-aa1ce88ebdd0 org.jenkinsci.plugins.credentialsbinding.impl.MaskedException: Command returned exit status 1: #!/bin/bash set -eo pipefail set -x OUTPUT_REPO="${params.OUTPUT_REPO}" REPO_URL="http://root:****@10.100.15.95:8181/lora/qwen-VL.git" LOCAL_OUTPUT="/opt/tmp/lora/20250918_173956/model_lora" TMP_CLONE="/tmp/git-upload/$OUTPUT_REPO" mkdir -p "$(dirname "$TMP_CLONE")" rm -rf "$TMP_CLONE" mkdir -p "$TMP_CLONE" cd "$TMP_CLONE" git init git config user.email "jenkins@auto.dev" git config user.name "Jenkins CI Bot" if [ -d "$LOCAL_OUTPUT" ] && [ -n "$(ls -A $LOCAL_OUTPUT)" ]; then cp -r "$LOCAL_OUTPUT"/* ./ else echo "⚠️ 输出目录为空或不存在" touch EMPTY_OUTPUT_PLACEHOLDER.txt fi if [ -z "$(ls -A .)" ]; then echo "🚫 无任何内容可提交" exit 0 fi git add . git commit -m "chore: upload fine-tuned output [ci skip]" || exit 0 encode_url() { python3 -c "import urllib.parse; print(urllib.parse.quote('$1', safe=''))" } GROUP=$(echo "$OUTPUT_REPO" | cut -d'/' -f1) PROJECT=$(echo "$OUTPUT_REPO" | cut -d'/' -f2) ENCODED_REPO=$(encode_url "$OUTPUT_REPO") STATUS_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/projects/$ENCODED_REPO") if [ "$STATUS_CODE" -ne 200 ]; then echo "🔧 仓库不存在,正在创建..." ENCODED_GROUP=$(encode_url "$GROUP") GROUP_ID=$(curl -s -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/groups/$ENCODED_GROUP" | jq -r '.id') if [ "$GROUP_ID" == "null" ]; then echo "❌ 无法获取 Group ID,请确认 '$GROUP' 存在" exit 1 fi curl -X POST \ -H "PRIVATE-TOKEN: ****" \ "http://10.100.15.95:8181/api/v4/projects" \ -d "name=$PROJECT&namespace_id=$GROUP_ID&description=Auto-created+for+LoRA+fine-tuning" \ || { echo "❌ 创建项目失败"; exit 1; } fi git remote add origin "$REPO_URL" || git remote set-url origin "$REPO_URL" git push -u origin main --force echo -e "\033[1;32m🎉 成功上传至 GitLab:$REPO_URL\033[0m" at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source) at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source) at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83) at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:77) at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrap.callConstructor(ConstructorSite.java:84) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:258) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.session.execution.Command$Helper.execute(Command.groovy:52) at jdk.internal.reflect.GeneratedMethodAccessor5302.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:151) at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.call(StaticMetaMethodSite.java:91) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:144) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.session.execution.Command$Trait$Helper.execute(Command.groovy:30) at org.hidetake.groovy.ssh.session.execution.Command$Trait$Helper$execute$0.call(Unknown Source) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.session.SessionHandler.execute(SessionHandler.groovy) at jdk.internal.reflect.GeneratedMethodAccessor5300.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:169) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:71) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:136) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.session.execution.Command$Trait$Helper.execute(Command.groovy) at org.hidetake.groovy.ssh.session.execution.Command$Trait$Helper$execute.call(Unknown Source) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.session.SessionHandler.execute(SessionHandler.groovy) at jdk.internal.reflect.GeneratedMethodAccessor5299.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:352) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:68) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:169) at PluginClassLoader for ssh-steps//org.jenkinsci.plugins.sshsteps.SSHService$_executeCommand_closure3$_closure13.doCall(SSHService.groovy:182) at PluginClassLoader for ssh-steps//org.jenkinsci.plugins.sshsteps.SSHService$_executeCommand_closure3$_closure13.doCall(SSHService.groovy) at jdk.internal.reflect.GeneratedMethodAccessor5298.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:264) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:41) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:56) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.util.Utility.callWithDelegate(Utility.groovy:17) at jdk.internal.reflect.GeneratedMethodAccessor4848.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.invoke(StaticMetaMethodSite.java:46) at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:102) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:217) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.session.SessionTask.wetRun(SessionTask.groovy:64) at jdk.internal.reflect.GeneratedMethodAccessor5267.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:161) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.session.SessionTask.call(SessionTask.groovy:48) at java_util_concurrent_Callable$call$0.call(Unknown Source) at PluginClassLoader for ssh-steps//org.hidetake.groovy.ssh.core.Service.run(Service.groovy:81) at org.hidetake.groovy.ssh.core.Service$run$0.call(Unknown Source) at PluginClassLoader for ssh-steps//org.jenkinsci.plugins.sshsteps.SSHService.executeCommand(SSHService.groovy:177) at PluginClassLoader for ssh-steps//org.jenkinsci.plugins.sshsteps.steps.CommandStep$Execution$CommandCallable.execute(CommandStep.java:89) at PluginClassLoader for ssh-steps//org.jenkinsci.plugins.sshsteps.util.SSHMasterToSlaveCallable.call(SSHMasterToSlaveCallable.java:35) at hudson.remoting.LocalChannel.call(LocalChannel.java:47) at PluginClassLoader for ssh-steps//org.jenkinsci.plugins.sshsteps.steps.CommandStep$Execution.run(CommandStep.java:77) at PluginClassLoader for ssh-steps//org.jenkinsci.plugins.sshsteps.util.SSHStepExecution.lambda$start$0(SSHStepExecution.java:88) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) at java.base/java.util.concurrent.FutureTask.run(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) Finished: FAILURE
最新发布
09-19
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值