前言
在一个自动化编译部署系统里面,使用scp命令远程复制文件是很正常的,然而使用jenkins出现了该问题。
具体来源于:
[Host key verification failed -解决jenkins调用脚本scp进行远程复制时候的权限问题(初稿)]
(https://blog.csdn.net/cdnight/article/details/81078191)
此篇文章作为整理。
环境还原
在一个pipeline任务里面,编译流水任务代码如下:
#!/usr/bin/env groovy
pipeline{
agent any
environment {
REVISION = "0.0.${env.BUILD_ID}"
}
options{
disableConcurrentBuilds()
skipDefaultCheckout()
timeout(time: 1, unit: 'HOURS')
timestamps()
}
parameters{
choice(name: 'build_env', choices: 'dev\ntest\nproduct\n', description: '请选择构建的环境')
}
stages{
stage ('Initialize') {
steps {
script {
currentBuild.displayName = "${REVISION}"
}
sh '''
echo "任务初始化..."
echo "构建版本revision:${REVISION}"
'''
sh '''
echo "项目检出...."
'''
checkout([$class: 'SubversionSCM',
additionalCredentials: [],
excludedCommitMessages: '',
excludedRegions: '',
excludedRevprop: '',
excludedUsers: '',
filterChangelog: false,
ignoreDirPropChanges: false,
includedRegions: '',
locations: [[credentialsId: 'e522721e-4a9a-467c-b154-acb803d8afb0',
depthOption: 'infinity',
ignoreExternalsOption: true,
remote: 'svn://127.0.0.1:3690/MicroBaseModule']],
workspaceUpdater: [$class: 'UpdateUpdater']])
}
}
stage ('Build') {
steps {
echo "您选择了:${params.build_env}"
echo '构建阶段....'
echo '构建部署 MicroBaseApi子项目...'
sh "mvn clean deploy -e -f MicroBaseModule/MicroBaseApi/pom.xml -P ${params.build_env}"
echo '构建打包MicroBaseApp子项目...'
sh "mvn clean package -e -f MicroBaseModule/MicroBaseApp/pom.xml -P ${params.build_env}"
}
}
stage ('Deploy') {
steps {
echo '发布阶段....'
script
{
if (params.build_env == 'test') {
echo '=====》》》测试环境进行远程发布。'
sh '''
sudo su -s /bin/bash jenkins
scp /var/lib/jenkins/workspace/MicroBase/MicroBaseModule/MicroBaseApp/target/MicroBaseApp-Build.zip root@x.x.x.x(你的远程机器地址):/data/packages/test/MicroBaseApp/MicroBaseApp-Build-${REVISION}.zip
'''
}
if(params.build_env=='product'){
echo '=====》》》生产环境进行远程发布。'
sh '''
sudo su -s /bin/bash jenkins
scp /var/lib/jenkins/workspace/MicroBase/MicroBaseModule/MicroBaseApp/target/MicroBaseApp-Build.zip root@x.x.x.x(你的远程机器地址):/data/packages/product/MicroBaseApp/MicroBaseApp-Build-${REVISION}.zip
'''
}
else {
echo '=====》》》 默认(开发)环境进行远程发布。'
sh '''
sudo su -s /bin/bash jenkins
scp /var/lib/jenkins/workspace/MicroBase/MicroBaseModule/MicroBaseApp/target/MicroBaseApp-Build.zip root@x.x.x.x(你的远程机器地址):/data/packages/dev/MicroBaseApp/MicroBaseApp-Build-${REVISION}.zip
'''
}
}
}
}
}
post {
always {
echo '构建结束...'
}
success {
echo '恭喜您,构建成功!!!'
}
failure {
echo '抱歉,构建失败!!!'
}
unstable {
echo '该任务已经被标记为不稳定任务....'
}
changed {
echo ''
}
}
}
执行结果:
异常。
检查及诊断
1、检查jenkins系统账户,完成切换+免密登录
jenkins系统本身有bug的。jenkins安装以后系统会多了一个jenkins用户,如果你切换过去,是切换失败的,例如:
su jenkins
可以看到切换不成功依然是root账号的。
1、解决无法切换jenkins用户的问题。
根源及解释:
/etc/passwd文件中的/bin/bash被yum安装的时候变成了/bin/false.
1
然后我执行cat /etc/passwd命令,果然被改成了/bin/false
cat /etc/passwd
1
接着执行sudo vim /etc/passwd命令,把false改为bash
sudo vim /etc/passwd
1
修改完毕后,执行su jenkins命令。
sudo vim /etc/passwd
改为:
然后执行:
su jenkins
2、解决用户名不是jenkins而是bash的bug
结果新的问题又来啦
当我切换到jenkins用户后,命令提示符的用户名不是jenkins而变成了
-bash-4.1#
网上一查,原因是在安装jenkins时,jenkins只是创建了jenkins用户,并没有为其创建home目录。所以系统就不会在创建用户的时候,自动拷贝/etc/skel目录下的用户环境变量文件到用户家目录,也就导致这些文件不存在,出现-bash-4.1#的问题了
以下命令是在切换到jenkins用户下执行的!(只是用户现在显示的是-bash-4.1)
这个时候呢,参考网上的做法我执行下面步骤:
①vim ~/.bash_profile
执行上面的命令,即使没有.bash_profile文件,linux会自动创建。
②然后再添加这句
export PS1='[\u@\h \W]\$'
1
PS1:命令行提示符环境变量
1
2
具体可以参考:http://zhidao.baidu.com/link?url=rMCdJazfyycZlY5xN-peNO-pUwTcPMROlXvrZZjE2EV9fDA7513e1JsiGXiWPlBWgArqrHNGu4yBvwNSY0Y79_
③我们最后再刷新.bash_profile文件,使其起作用
source ~/.bash_profile
首先:
然后:
source ~/.bash_profile
3、账号开启免密登录
当你要执行jenkins任务时候你可能会发现出现这个问题:
根源有:
解释一二没看出大区别,不过解释2详细,按照解释2来执行:
sudo: no tty present and no askpass program specified
由于帐号并没有开启免密码导致的
假设当前帐号为abc
切换到root下
1 打开sudoers
vi /etc/sudoers
2 添加免密码
abc ALL = NOPASSWD: ALL
文章标签: linux present and no askpa
靠谱的解释:
在Jenkins的使用过程中,如果在脚本中使用到sudo命令,有可能出现如下所示的错误:
sudo: no tty present and no askpass program specified
这是因为Jenkins服务器在执行sudo命令时的上下文有误,导致这个命令执行的异常。
解决方案:
在Jenkins宿主服务器上运行如下命令
$ sudo visudo
在文件的末尾加上一行
jenkins ALL=(ALL) NOPASSWD: ALL
保存文件(注意保存的时候修改文件名,文件名后缀不要加上默认的.tmp,即可覆盖原文件)
Ctrl+O
退出编辑
Ctrl+X
重启Jenkins服务
$ /etc/init.d/jenkins restart
最后,重新执行构建任务,不会出现先前的错误。
PS:如果误操作修改了/etc/sudoers的权限来修改上述文件,则会导致如下所示的错误:
sudo :/etc/sudoers is world writable
sudo : no valid sudoers source found, quitting
sudo : unable to initialize poling plugin
这是Linux的一种保护机制。因此,如果出现上述误操作,则需要执行如下命令来解决:
$ pkexec chmod 0440 /etc/sudoers
好,试试:
sudo visudo
后面加上:
jenkins ALL=(ALL) NOPASSWD: ALL
/etc/init.d/jenkins restart
重启,然后测试一下是不是还要密码:
测试成功,jenkins免密登录成功。
ssh免密登录
scp的免密执行其实取决于ssh的免密登录。假如ssh能够免密登录的话那么jenkins就可以直接调用scp不用输入密码了,当然就可以自动执行不用人工干预了。
接下来,应该要进行的是免密远程ssh登录了,按照前面英文的提示。
当然,各位可以看看这篇资料:CentOS如何开启ssh远程连接
下面是主要内容的引用:
假设VPS采用centos,再假设用较新版本6.5。
VPS上可能没有安装桌面,但一般来说都会安装ssh,并且防火墙默认开放22端口。
那就从ssh开始。
# 安装ssh,默认已安装好
# yum install ssh
# 启动ssh服务器端
# service sshd start
# chkconfig sshd on
ssh登陆
如果本地端是Linux
# ssh root@192.168.1.1
其中root表示的是登录用户名,192.168.1.1为主机的IP地址,当然也可以使用主机名、域名来指代IP地址。
# ssh 192.168.1.1
则会以当前客户端的用户名进行登录。
ssh无密码登录
但是每次输入密码登录十分麻烦,有没有一种方式可以让服务器能够确定我的身份,无需输入密码可以直接通过认证?
ssh除了使用密码验证外,还提供了一种公私密钥的验证方式。客户端生成一个私钥,并生成一个与之对应的公钥,然后将公钥上传到服务器上。下面是Linux示例。
在客户端生成私钥、公钥(注意,在客户端完成):
# ssh-keygen -t rsa
-t指定要创建的密钥类型,默认就是rsa了,所以只执行ssh-keygen是一样的。
期间会提示你输入你私钥的加密密码。如果需要完全脱离密码,此处可留空,直接回车,否则以后每次连接需要本地解锁。
完成后,会当前用户的主目录下的~/.ssh/路径下生成两个文件id_rsa与id_rsa.pub分别是私钥与公钥。
接下来,要把生成的公钥上传到服务器上,同样还是在客户端执行以下的代码。
# ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.1
其中root可以修改为你想要自动登录的服务器端用户名,192.168.1.1修改为你的VPS主机名或IP地址。
最后,ssh登录远程服务器。
# ssh root@192.168.1.1
此时就不需要密码就可以登录了。
1、ssh-keygen
#要先切换到jenkins的账户
su jenkins
#生成密钥,都选默认的。
ssh-keygen
然后,你可以看到已经有这份文件了。
cat /var/lib/jenkins/.ssh/id_rsa.pub
如下图:
接下来,测试ssh远程登录到目标机器:
ssh -p 你的ssh端口(默认是22) 你要登录的账号(通常为root)@你的远程ip地址
结果如下:
都要输入密码啊,我们要做到不输入密码就可以远程登录,key密钥是时候用了。
好了,具体到我们这里,这样来用:
#带端口的:
ssh-copy-id -i /var/lib/jenkins/.ssh/id_rsa.pub -p 你的端口号(通常为22) root@目标ip地址
#不带端口的:
ssh-copy-id -i /var/lib/jenkins/.ssh/id_rsa.pub root@目标ip地址
结果和测试:
好了,至此,在a机器上面使用jenkins账户免密ssh登录到b机器已经部署成功,scp大体如此。
再继续执行jenkins的pipeline任务:
好了,我们到目标机器看看有没有接收到这份文件:
好了,自动化部署中的jenkins调用自己账户,免密码上传文件已经解决
结语
估计目前专业的运维还是少了,很多情况都是码农在兼任的,网上关于这样的文章很多,不过要一步一步解决还真的是很多问题的,没有专业的linux知识及运维知识估计也是很呛了。
还有些压根是坑人的。
就拿jenkins来说,jenkins安装以后会新建一个jenkins账户,然而没办法正常切换jenkins这个账号,没办法在jenkins的pipeline脚本直接运行这种问题在jenkins搭建的文章中无一体验,可见都是摸着石头过河的。
所以,运维这一块也不轻松。