首先声明,除非万不得已,千万不要在Windows环境作这个事情,不然就等着各类坑吧。
本人一向的立场都是坚持用正确的方法作事,显然在Windows搭建Jenkins这个事情自己并不那么正确。
之因此有这篇随笔,也是由于经历了各类吐血踩坑以后但愿留个备忘。固然,若是此文能给阅读者带来帮助,那不胜荣幸。html
最近在作一个简单的数据采集项目,一开始只有一台远程主机,因此每次更新都是本地打包以后直接scp过去,而后再到目标主机上执行脚本。由于机器只有一台,作这些动做到也没以为不妥,由于就是简单的几步操做也犯不着还须要持续集成工具什么的。可是最近的数据量有所增长,因此必须增长新的远程主机,因此如今有了2台机器,每次都是执行文件上传,而后再依次登陆到每台主机上执行脚本。老是频繁打包更新时花费在这些重复性步骤上的时间累加起来也挺可观的,因而乎就想搭建一个Jenkins系统作一键发布。
之因此在Windows10环境折腾,是由于公司电脑就只有Windows10,其实在Linux环境操做的话也不会遇到以下这些问题了。java
第一步:安装Jekins。git
这一步没有问题,直接到官网下载安装包:jenkins.msi。
而后一步一步点击安装完成,因为安装的是Windows服务包,能够在Windows服务管理窗口中找到Jenkin后执行启动/中止操做。固然,也能够经过Jenkins自带的可执行程序来操做。
在Windows控制台进入到Jenkins安装目录,执行以下命令:github
jenkins.exe stop | start | restart
第二步:配置项目发布流程shell
主要的踩坑都是在这里遇到的。ssh
踩坑1 shell环境工具
为了能在Windows环境使用一些Unix/Linux命令,因此须要安装Cygwin,并添加到Windows环境变量Path中:Path=%Path%:C:\cygwin64\bin\
。
而后执行以下命令打包程序:tar czvf xxx.tar.gz xxx
,该命令在Cygwin命令行界面执行是没有任何问题的,可是到Jenkin中执行时就会报错:ui
Caused: java.io.IOException: Cannot run program "sh"
显然,Windows下的shell环境是cmd.exe,而上述打包命令并不能直接运行。this
解决办法:
在Jenkins中明确指定shell环境,设置路径:【Manage Jenkins】->【Configure System】-> 【Shell】,明确指定“Shell executable”,以下图所示:
命令行
注意: 虽然安装Cygwin后也带了“sh.exe”,可是在Jenkins中设置为“C:\cygwin64\bin\sh.exe”时依然不能执行命令,因此设置为Git客户端自带的sh.exe。
踩坑2: 文件上传
程序打包完毕以后,须要上传到远程主机。
在Linux主机之间传输文件一般经过scp命令实现,因而我也想在Windows上使用scp来作这个事情。
但遗憾的是经过Cygwin并不能安装scp命令,而微软PowerShell团队提供的Win32-OpenSSH项目正好带了scp命令。
到这里还算顺利,在安装了Win32-OpenSSH以后能够经过scp命令将文件传输到远程主机。
可是在执行scp命令时必须输入密码,显然在Jenkins中要实现一键部署时是没法执行输入密码这个动做的,所以就须要实现本地Windows主机与远程Linux主机之间的免密传输。
咱们知道,在Linux主机之间要实现免密传输文件,好比主机L1向主机L2传输文件,只须要将L1主机的公钥信息写在L2的~/.ssh/authorized_keys文件中便可,具体操做步骤以下:
首先,在主机L1上执行:ssh-keygen -t rsa
,而后将L1主机的~/.ssh/id_rsa.pub文件上传到L2主机上,并命名为id_rsa_L1.pub
其次,在主机L2上执行:cat id_rsa_L1.pub >> ~/.ssh/authorized_keys
完成上述设置以后,在主机L1上经过scp命令向主机L2传输文件时就能够不用每次都输入密码了,这大大简化了主机之间文件传输的流程,也是在Jenkins中能够实现一键部署的关键。
但很是遗憾的是,在个人实践中,这一步并无成功!我尝试了不少次将本地Windows主机的ssh公钥写到远程Linux主机的~/.ssh/authorized_keys文件中,每次执行scp命令时依然须要手动输入密码。
另外,使用Cygwin提供的sshpass命令明确指定密码也一样不能成功!
显然,若是没法避开手动输入密码这个步骤,是没法在Jenkins中实现一键部署的。
通过一番搜索后知道:在Windows环境要实现相似于scp命令的功能,还能够经过一个叫作pscp的命令实现,而且pscp命令有一个-pw
选项参数能够指定远程主机的登陆密码,这样就能够实现不用手动输入密码的效果了。
pscp命令有如下2种方式获取:
(1)Putty安装包默认已经带了pscp.exe程序,因此只须要安装Putty便可,注意必定要选择“Windows Installer”安装包默认才带pscp.exe。
(2)Gow工具包也默认带有pscp.exe程序:前面咱们说过,在Windows环境要执行一些Unix/Linux命令能够经过安装Cygwin来实现,但遗憾的是Cygwin中却不带pscp.exe,而Gow是另外一个包含了大量Unix/Linux命令的工具集,能够做为Cygwin的轻量级替代品来使用。
我选择了经过安装Putty来使用pscp命令。
安装好Putty以后,须要将Putty的安装路径添加到Jenkins中,设置路径:【Manage Jenkins】->【Configure System】-> 【Global properties】-> 【Environment variables】,设置Name为“Path”的变量值,以下图所示:
注意: Putty的安装路径只能经过在Jenkins中设置Path变量的方式添加才能生效,而设置在主机的Path变量中并不能生效。
此时,彷佛准备工做都已经就绪,能够经过pscp命令传输文件了,因而在Jekins中执行以下命令:
pscp -pw xxx xxxx.tar.gz root@192.168.56.101:/root
可是!却意外地报错了:
ssh_init: Network error: Cannot assign requested address Build step 'Execute shell' marked build as failure Finished: FAILURE
因而继续搜索解决办法,看到Stack Overflow上有人提过ssh_init: Network error: Cannot assign requested address的问题,须要指定端口。
因而明确指定端口再次执行:
pscp -P 22 -pw xxx xxxx.tar.gz root@192.168.56.101:/root
继续报错:
The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is. The server's ssh-ed25519 key fingerprint is: ssh-ed25519 255 74:3b:39:b1:c3:e8:6c:a2:88:46:b1:46:dd:58:e9:5a If you trust this host, enter "y" to add the key to PuTTY's cache and carry on connecting. If you want to carry on connecting just once, without adding the key to the cache, enter "n". If you do not trust this host, press Return to abandon the connection. Store key in cache? (y/n) Connection abandoned. Lost connection Build step 'Execute shell' marked build as failure Finished: FAILURE
根据提示信息能够知道,大概是没法确保目标主机是可信任的,须要手动确认(有点相似于在使用scp命令时须要手动输入密码的意思)。
因为在Jenkins中执行命令是没法手动参与的,因此继续寻找解决办法,一样在Stack Overflow上看到有人提出相同的疑问:getting-the-servers-host-key-is-not-cached-in-the-registry-when-using-pscp-ex。
解决办法是经过pscp的选项参数-hostkey
明确指定远程主机的指纹信息(这个指纹信息就是上述错误信息中提示一段十六进制串:74:3b:39:b1:c3:e8:6c:a2:88:46:b1:46:dd:58:e9:5a),再次执行命令以下:
pscp -P 22 -pw xxx -hostkey 74:3b:39:b1:c3:e8:6c:a2:88:46:b1:46:dd:58:e9:5a xxxx.tar.gz root@192.168.56.101:/root
终于成功了!!!
到这里,无需手动输入密码的文件传输终于解决了,因而后续的其余配置也均可以顺利进行。
以下,对在Windows环境执行Unix/Linux命令作一下小小的总结。
第一,在Windows环境中执行Unix/Liunx命令能够经过安装工具集Cygwin或Gow来实现,固然,也有可能还须要安装OpenSSH。
第二,在Windows环境下的Jenkins执行Unix/Linux命令须要使用Git客户端提供的sh.exe环境。
第三,在Windows环境下要实现免输入密码方式的文件传输,只能使用pscp.exe来实现,而且在Jenkins中执行时还必须明确指定端口(-P 22)和远程主机的指纹信息(-hotkey xx:...)。
最后的最后,仍是要再次告诫你们,除非万不得已,千万不要在Windows环境折腾Unix/Linux命令的事情,坑太多了!
【参考】
https://stackoverflow.com/questions/62817854/ssh-init-network-error-cannot-assign-requested-address
https://stackoverflow.com/questions/42841923/getting-the-servers-host-key-is-not-cached-in-the-registry-when-using-pscp-ex