我有一种奇怪的设置,我需要在sh
Jenkinsfile 的一个块中以 docker 容器的形式运行命令。
我所面临的问题具体与awk
用于修剪输出的命令有关。
这是命令工作正常当跑的时候直接在 bash shell 上:
OPFILENAME=$(docker run -t \
-e AWS_SECRET_ACCESS_KEY='<omitted>' \
-e AWS_ACCESS_KEY_ID='<omitted>' \
-e AWS_DEFAULT_REGION='us-east-1' \
mydockerimage:0.1 \
bash -c "aws s3 ls my-bucket-name/dir/ | sort | tail -n 1 | awk '{print \$4}' ") && \
echo $OPFILENAME
所以我需要通过 Jenkins 管道在远程主机上运行完全相同的东西,下面是一般语法:
pipeline {
agent any
environment {
BUILDHOST = 'buildhost.example.com'
SSHCMD = "ssh -o StrictHostKeyChecking=no jenkins@${env.BUILDHOST}"
}
stages {
stage('Get filename from s3') {
steps {
sshagent ( ['ssh_config']) {
sh """${SSHCMD} '''
OPFILENAME=\$(sudo docker run -t \
-e AWS_SECRET_ACCESS_KEY='<omitted>' \
-e AWS_ACCESS_KEY_ID='<omitted>' \
-e AWS_DEFAULT_REGION='us-east-1' \
mydockerimage:0.1 \
bash -c "aws s3 ls my-bucket-name/dir/ | sort | tail -n 1 | awk '{print \$4}') && \
echo \$OPFILENAME
'''
"""
}
}
}
}
}
这是 Jenkins 抛出的错误:
...bash -c "aws s3 ls my-bucket-name/dir/ | sort | tail -n 1 | awk {print' '}") && echo $OPFILENAME "
'
bash: -c: line 1: unexpected EOF while looking for matching `"'
bash: -c: line 3: syntax error: unexpected end of file
注意它是如何转换awk
命令的:awk {print' '}
尝试各种更改:...| sort | tail -n 1 | awk \'{print \$4}\'")
导致完全相同的错误。
像这样尝试awk "'{print \$4}'"
:不会抛出错误但在日志中它显示如下:awk "{print' '}"
因此所需的 awk 修剪不会发生。哎呀!
所以我知道引用有问题,而且由于我在多行命令中使用了三重引号,所以它变得更加混乱!
我参考了这个要点,试图弄清楚如何做到这一点:https://gist.github.com/Faheetah/e11bd0315c34ed32e681616e41279ef4但仍然遇到一个又一个问题。
注意事项: - 命令必须在sshagent
块中和远程主机上运行。命令不能在本地 Jenkins 工作区中运行。
答案1
'{print \$4}'
该错误是由于和之间缺少双引号造成的)
。 您在原始脚本中有它,但在 Jenkinsfile 中没有。
话虽如此,这是一个非常困难的问题,因为多个进程将剥离/处理引文。首先是 Groovy 本身。然后是 Jenkin 的sh
命令(加上命令将启动的 shell 进程),然后是ssh
,然后是将启动的远程 shell ssh
,然后是bash
您启动的。其中之一是删除\
之前的$4
,这会破坏您的 AWK 脚本。
您可以尝试使用awk -f script
或使用sed
将多个空间折叠为一个然后使用来解决此特定问题cut
:... | sed -e 's/ +/ /g' | cut -d " " -f 4 | ...
但最终它总是脆弱的。
我强烈建议创建一个脚本文件,将其复制到远程主机并运行ssh bash ./script.sh
。这将消除很多麻烦。最重要的是,您将能够从命令行测试和调试脚本,而无需在每次更改后都经过 Jenkins。
或者,将大部分脚本放入自定义 docker 镜像并选择其作为该镜像的默认命令。
使用SSH 管道步骤插件可能会有帮助,因为它有一个选项“sshScript”,它可以将脚本复制到远程服务器,然后在那里执行它:https://github.com/jenkinsci/ssh-steps-plugin#sshscript