原文: Linux遠(yuǎn)程無密傳輸實(shí)現(xiàn)腳本
date: 2017-05-15 12:39:04
序言
作為一名后臺(tái)開發(fā), 開發(fā)過程中, 除了要部署后臺(tái)的微服務(wù), 還要對(duì)前端的WEB目錄進(jìn)行部署.
雖然每次只需要2分鐘左右, 但卻是重復(fù)性勞動(dòng). 我認(rèn)為很xx!
聽說過俄羅斯一程序員, 認(rèn)為90秒以上的事情, 就必須要做成腳本, 比如煮咖啡, 騙老婆說要加班等等…
所以我決定花幾個(gè)小時(shí)時(shí)間來把這種事情寫成腳本.
目前公司的前端WEB目錄部署其實(shí)就是文件的上傳下載, 不需要啟動(dòng)什么的.
既然前端人員不想用Linux也不想用FTP.
那… 在linux下編寫成腳本后, 讓前端人員直接在windows下通過一個(gè)按鈕點(diǎn)擊, 就完成WEB目錄的一鍵部署.
我就完全可以脫身這件事.
場(chǎng)景描述
首先預(yù)上線環(huán)境部署WEB目錄的流程:
- 開發(fā)環(huán)境: 213
- 測(cè)試環(huán)境: 212
- 預(yù)上線環(huán)境: 110
前兩個(gè)環(huán)境是我來手動(dòng)維護(hù), 因?yàn)閷懥撕芏嗄_本(自動(dòng)Git拉取, Maven打包, 一鍵殺死/啟動(dòng)微服務(wù)等…)
所以維護(hù)起來很輕松.
110環(huán)境是通過Jenkins來構(gòu)建的, 每次構(gòu)建完成都會(huì)生成全新的虛擬機(jī)鏡像
服務(wù)器, 數(shù)據(jù)庫, Redis都會(huì)是新的(IP不變)
所以WEB目錄的部署, 是在212上拉取測(cè)試通過的目錄到預(yù)上線的WEB目錄.
但是經(jīng)常會(huì)有bug修正, 每次修正完又要重新拉一遍.
所以阿. 看起來這個(gè)腳本應(yīng)該很簡(jiǎn)單. 就是copy主機(jī)A的WEB目錄到主機(jī)B
建立通信
但是涉及到兩臺(tái)機(jī)器通信, 就會(huì)有密碼. 總不能執(zhí)行腳本之后再來輸入密碼.
有以下兩種方式:
- ssh免密:建立互信關(guān)系
- 通過expect自動(dòng)輸入
方式一: ssh
關(guān)于什么是ssh, 公鑰, 密鑰 原理什么的可以Google 簡(jiǎn)單介紹下操作方法:
假設(shè)現(xiàn)在有
- A(192.168.100.212)
- B(192.168.100.213)
兩臺(tái)機(jī)Linux(CentOS7), 要實(shí)現(xiàn)從A用ssh遠(yuǎn)程登錄到B:
1. 首先在A上生成公鑰
ssh-keygen -t rsa
這里一直點(diǎn)回車即可.
執(zhí)行完成后, 在~/.ssh/下就會(huì)生成id_rsa和id_rsa.pub兩個(gè)文件
2. 把A機(jī)器剛才生成的id_rsa.pub文件復(fù)制到B上.
scp ~/.ssh/id_rsa.pub root@192.168.100.213:/root/
然后在B的root目錄下就能看到id_rsa.pub了(這里放root下只是臨時(shí)放一下, 你放哪都行)
3. 在B機(jī)器中, 把id_rsa.pub中的內(nèi)容加到authorized_keys文件
cat id_rsa.pub >> ~/.ssh/authorized_keys
如果~/下沒有.ssh或者.ssh下沒有authorized_keys, 就自己手動(dòng)創(chuàng)建
4. 在B上重啟sshd服務(wù)
service ssh restart
完了, 現(xiàn)在在A上, 試試登陸B(tài): ssh root@192.168.100.213. 應(yīng)該就不輸入密碼了
注意事項(xiàng):
- ssh-keygen -t rsa 生成公鑰時(shí)一直回車不要輸入密碼,就是空密碼
- 要用哪個(gè)用戶遠(yuǎn)程登錄就把
id_rsa.pub復(fù)制到用戶對(duì)應(yīng)路徑下,如:root用戶就復(fù)制到/root/下; xxx用戶就復(fù)制到/home/xxx/下,不要混了 - B機(jī)上的文件權(quán)限:
.ssh文件夾(700);authorized_keys(600)
方式二: expect
在我寫這個(gè)腳本時(shí)候, 并未使用上面那種方法.
原因是上面提到過, 每次預(yù)上線環(huán)境構(gòu)建完都會(huì)是一臺(tái)全新虛擬機(jī)(只有IP不變)
所以不可能每次構(gòu)建完都去配一次ssh信任關(guān)系.
所以介紹一種更優(yōu)雅的方式, 在腳本里自動(dòng)輸入密碼(當(dāng)屏幕交互需要輸入時(shí)自動(dòng)輸入)
這里用到的就是expect.
要使用首先要安裝:
sudo yum install expect
建立scp.exp
#!/usr/bin/expect
set timeout 20
if { [llength $argv] < 2} {
puts "Usage:"
puts "$argv0 local_file remote_path"
exit 1
}
set local_file [lindex $argv 0]
set remote_path [lindex $argv 1]
set passwd your_passwd
set passwderror 0
spawn scp $local_file $remote_path
expect {
"*assword:*" {
if { $passwderror == 1 } {
puts "passwd is error"
exit 2
}
set timeout 1000
set passwderror 1
send "$passwd\r"
exp_continue
}
"*es/no)?*" {
send "yes\r"
exp_continue
}
timeout {
puts "connect is timeout"
exit 3
}
}
這里我找到一個(gè)比較通用的(除了輸入自動(dòng)輸入密碼之外, 還支持yes/no的自動(dòng)選擇)
可以看到第一行并不是#!/bin/bash. 所以這段腳本不是由bash解釋執(zhí)行, 而是expect.
代碼的語法和shell也不一樣.
set local_file [lindex $argv 0] # 本地要拷貝的文件
set remote_path [lindex $argv 1] # 遠(yuǎn)程拷貝文件的目標(biāo)地址
set passwd your_passwd #your_passwd就是你要連接遠(yuǎn)程機(jī)器的密碼
spawn scp $local_file $remote_path # 這個(gè)就是實(shí)際的拷貝, 如果要復(fù)制目錄下的文件, 可以加-r以遞歸方式復(fù)制
例如我要把本機(jī)(213)的某個(gè)文件復(fù)制到主機(jī)110上
./scp.exp /hahah/hello.py root@192.168.120.110:/xx/yy/
scp目錄的坑
對(duì)于上述第二種方式: scp的目錄問題, 有個(gè)坑記錄一下
例如:
/scp.exp /hahah/hello.py root@192.168.120.110:/xx/yy/: 是把hello.py文件拷貝到y(tǒng)y目錄下, 沒問題../scp.exp /hahah/dir1 root@192.168.120.110:/xx/yy/: 是把dir1目錄拷貝到y(tǒng)y目錄下, 也沒問題-
./scp.exp /hahah/dir1/ *root@192.168.120.110:/xx/yy/: 按理說應(yīng)該是把dir1目錄下的文件(不包括dir1目錄本身)拷貝到y(tǒng)y目錄下.這個(gè)直接在scp命令下是沒問題的. 但是因?yàn)檫@里執(zhí)行的是scp.exp腳本.
他會(huì)直接把*當(dāng)成特殊字符, 所以需要”\”來轉(zhuǎn)義, 例如:
./scp.exp /hahah/dir1/* root@192.168.120.110:/xx/yy/
方便調(diào)用scp.exp
兩種通信方式就介紹完了.
因?yàn)槲乙ㄟ^一個(gè)請(qǐng)求去調(diào)用scp腳本. 為了方便, 又寫了一個(gè)腳本去調(diào)用scp.exp
update_pre_online.sh內(nèi)容如下:
#!/bin/bash
echo "Content-Type: text/html"
echo ""
# Source path
SRC_PATH=/home/www/update_pre_online/xxws-web-120/
# Target path and Ip address
#TAG_PATH=/home/xiefy/dir/
#TAG_ADDRESS=192.168.100.214
TAG_PATH=/sysroot/tmp/xxws/
TAG_ADDRESS=192.168.120.110
# Pull 212WEB to 213WEB
scp -r root@192.168.100.212:/home/www/xxws-web/* ${SRC_PATH}
chmod -R 755 ${SRC_PATH}
echo "============================"
echo "遞歸修改目錄訪問權(quán)限(755)..."
echo "============================"
sleep 1
# execute expect, pull to 110WEB
/home/www/update_pre_online/scp.exp ${SRC_PATH}\* root@${TAG_ADDRESS}:${TAG_PATH}
cat ~/update_pre_online.log
echo "--------------------------------------"
echo " 更新 212WEB目錄 到 110WEB目錄 成功! "
#echo " 禁止更新! 新的預(yù)上線后臺(tái)微服務(wù)未更新 "
echo "--------------------------------------"
sleep 2
exit 0
總結(jié)
完成后, 加一個(gè)小頁面按鈕, 效果如下:

雖然之前部署這個(gè)熟練的話每次只需要三分鐘.
但我編寫腳本加測(cè)試就用了好幾個(gè)小時(shí).
成果就是現(xiàn)在每次只需要點(diǎn)擊按鈕后等待5秒即可, 最重要的是!!! 不需要我來操作了.
The End