轉 在shell腳本中使用expect實現scp傳輸問題 以及自動化遠程部署


 

 

1.安裝expect

expect用於shell腳本中自動交互,其是基於tcl編程語言的工具。所以安裝expect首先安裝tcl。本文中使用的是expect5.45tcl8.6.6

安裝tcl

[root@tseg0 /]$ mkdir /tools [root@tseg0 /]$ tar -zxvf tcl8.6.6-src.tar.gz [root@tseg0 /]$ cd tcl8.6.6/unix/ [root@tseg0 /]$ ./configure [root@tseg0 /]$ make [root@tseg0 /]$ make install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

安裝expect

[root@tseg0 /]$ cd /tools [root@tseg0 /]$ tar -zxvf expect5.45.tar.gz [root@tseg0 /]$ cd expect5.45/ [root@tseg0 /]$ ./configure --with-tcl=/usr/local/lib/ --with-tcl include=/tools/tcl8.6.6/generic/ [root@tseg0 /]$ make [root@tseg0 /]$ make install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

shell腳本實現scp傳輸

命令解釋

-c 表示可以在命令行下執行except腳本; 
spawn 命令激活一個unix程序來交互,就是在之后要執行的命令; 
expect “aaa” 表示程序在等待這個aaa的字符串; 
send 向程序發送字符串,expect和send經常是成對出現的,比如當expect“aaa”的時候,send“bbb”。

執行腳本

#! /bin/sh expect -c " spawn scp -r /home/tseg/hello $name@10.103.240.33:/home/$name/ expect { \"*assword\" {set timeout 300; send \"$pass\r\"; exp_continue;} \"yes/no\" {send \"yes\r\";} } expect eof"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

解釋: 
第二行: -c 表示可以不用與控制台交互; 
第三行:spawn激活一個scp的unix程序; 
第五行:expect期待含有“assword”的字符串,設置連接時間最大為300毫秒,如果出現這個字符串,就send 變量pass代表的密碼字符串, exp_continue表示執行下面的匹配; 
第六航:expect期待含有“assword”的字符串,設置連接時間最大為300毫秒,如果出現這個字符串,就send 變量pass代表的密碼字符串; 
第八行:表示結束。

 

 

####sample 1:

1.vi 1.sh

#! /bin/sh

export pass=123456
export name=root
expect -c " spawn scp -r /home/tseg/hello $name@10.103.240.33:/home/$name/ expect { \"*assword\" {set timeout -1; send \"$pass\r\"; exp_continue;} \"yes/no\" {send \"yes\r\";} } expect eof"



set timeout -1   ------->>>>>>注意此處的-1,-1表示永不超時,也就是:等 scp 命令正常執行完成之后,控制權會轉移到下一行。  

set timeout 300  ------->>>>>>300表示300秒后超時,在超時之后,控制權會轉移到下一行;若在超時時間之內,程序運行完,則控制權也會轉移到下一行。  




2. nohup sh 1.sh


轉自 http://blog.csdn.net/BlockheadLS/article/details/52980797

####sampe 2

感謝https://www.jianshu.com/p/71e9c9a9c31f

shell 腳本sftp 文件下載

Mr_Alfred
2019.04.01 15:24:46字數 0閱讀 1,454
#!/bin/bash
sftp_Host="192.168.1.1"
sftp_userName="admin"
sftp_passWord="admin"
sftp_port=22
sftpRemotePath="/data/fiels"
sftpLocalPath="/root/sftp"
current=$(date "+%Y-%m-%d %H:%M:%S")

echo "當前時間是:$current"

if [[ $# == 0 ]]; then
    yesterday=$(date "+%Y%m%d" -d "-1 days")
fi
if [[ $# == 1 ]]; then
    yesterday=$1
fi
myDir=$sftpLocalPath
if [[ ! -d $myDir ]]; then
    mkdir -p $myDir
fi
sftpLoadPath=$sftpRemotePath$yesterday
fileFilter=$yesterday*.gz

# SFTP非交互式操作
sftp_download()
{
    expect <<- EOF
    set timeout 5
    spawn sftp  -P $sftp_port $sftp_userName@$sftp_Host

    expect { 
        "(yes/no)?" {send "yes\r"; expect_continue }
        "*assword:" {send "$sftp_passWord\r"}
    }
    expect "sftp>"
    send "cd $sftpLoadPath \r"
    expect "sftp>"
    send "lcd $myDir \r"
    expect "sftp>"
    set timeout -1
    send "mget $fileFilter \r"
    expect "sftp>"
    send "bye\r"
EOF
}

unGzipFiles(){
    cd $myDir
    fileList=`ls *`
    fileArr=($fileList)
    for fileName in ${fileArr[@]}
    do
        echo "開始解壓文件:$fileName"
        gzip -d  $fileName
    done

}

reNameFiles(){
    cd $myDir
    fileList=`ls *`
    fileArr=($fileList)

    for fileName in ${fileArr[@]}
    do
        echo "reNameFile :$fileName"
        mv $fileName $fileName".csv"
    done  
}

echo "執行sftp下載操作 : 數據日期:$yesterday"
sftp_download
echo "$yesterday 文件下載完成"
echo "執行解壓操作"
unGzipFiles
echo "重命名文件"
reNameFiles

 

 

 

########感謝 

linux expect中的timeout設定

在做日志分析工具時,發現在屏幕上拿到日志結果會有點慢,然后查了一下expect ssh timeout的設置,原來是這里有個默認時間的問題,所以整理一下:

expect腳本我們都知道,首先spawn我們要執行的命令,然后就給出一堆expect的屏幕輸出,如果輸出match了我們的expect的東西,我們就會send一個命令上去,模擬用戶輸入。

但是expect中等待命令的輸出信息是有一個timeout的設定的,默認是10秒。這個特性是防止那些執行死機的命令的。一旦到了這個timeout,還是沒有屏幕輸出的話,expect腳本中下面的代碼就會執行。或者我們在expect腳本中如果定義了timeout的響應代碼的話,這些代碼就會被執行。 

解決這樣的問題非常簡單,最簡單的辦法就是在expect腳本的開頭定義: 

set timeout -1 -- 沒有timeout set timeout XX -- 設定具體的timeout時間(秒)

 

 

###sample 

感謝吳老師

expect交互式安裝軟件
公司一些宿主機需要安裝軟件,吳老師要求寫一個安裝腳本;

腳本思路:首先要把安裝的包拷貝到每台機器上,然后要讓每台機器都運行一次安裝命令;就想到了應用scp、ssh命令,但這兩個命令需要輸入對端密碼,需要與機器交互;此時可以應用交互式命令expect。

expect可以實現自動交互:

  set:設置變量;set timeout -1,永不超時;set timeout 300,300秒后沒有expect內容出現退出;

  spawn:想要執行的命令,你想要進行的交互命令;

  expect:等待命令提示信息,交互的過程,系統會給一些輸入密碼等提示,expect就是抓取其中關鍵字,當expect抓取到了后面的關鍵字,就會執行send。

  send:發送信息,完成交互,檢測到關鍵字后向交互界面輸入的信息。

  interact:

  expect eof:結束退出;

代碼如下:


#!/bin/bash
#
SERVERS="192.168.254.11 192.168.254.12 192.168.254.13"  //需要安裝的所有主機
PASSWORD="123456"  //統一密碼
VIB_FILE="/app/vmware-esx-MegaCli-8.07.07.vib"  //安裝包路徑
SHELL_FILE="/app/megacli_install.sh"  //安裝腳本(腳本中就一條安裝vib文件的命令)

vib_shell_copy(){
expect << EOF
set timeout -1  //設置超時時間
spawn scp -o StrictHostKeyChecking=no $VIB_FILE $SHELL_FILE $1:/tmp/  //spawn調用scp命令將安裝包和安裝腳本copy到$1主機的tmp目錄下
expect "assword:"   //檢測關鍵信息
send "$2\r"  //輸出信息$2(密碼),通過scp密碼交互
expect eof  //完成expect
EOF
}


vib_install(){
expect << EOF
set timeout -1
spawn ssh -o stricthostkeychecking=no root@$1 "sh /tmp/megacli_install.sh"
expect "assword:"
send "$2\r"
expect eof
EOF
}

for SER in $SERVERS
do vib_shell_copy $SER $PASSWORD &> /dev/null
echo "$SER copy successed"
vib_install $SER $PASSWORD &> /dev/null
echo "$SER install successed"
done

測試了一下腳本沒問題,在生產運行腳本,第四五台機器時腳本就走不動了,咨詢一下吳老師,是scp、ssh命令會有首次交互確認的問題,選項 -o stricthostkeychecking=no 關閉主機密鑰檢查就OK了。

標簽: Linux shell

 

 

 


巧用expect安裝插件 原創
2020-02-06

劍俠闖江湖

碼齡16年

關注
背景
某產品的插件基本都是一步步安裝,需要輸入一些相對比較專業的參數,對於沒有接觸過該產品的人而言,就不知道怎么選擇。而某客戶對於該插件的需求是恆定的,則可以通過expect來自動執行安裝,降低了對售后人員的技術要求。

解決方法
!/usr/bin/expect
spawn bash install.bin
set openstack 11
expect "*1*12*select:" { send "$openstack\r" }
set install 1
expect "*operation:" { send "$install\r" }
set expert n
expect "*expert*:" { send "$expert\n" }
set sdnip 2009:d::101
expect "*sdn*" { send "$sdnip\n" }
set https y
expect "*HTTPS*:" { send "$https\n" }
set ssl n
expect "*validation*" { send "$ssl\n" }
set port 8443
expect "*8443*" { send "$port\n" }
set username root
expect "*name:" { send "$username\n" }
set passwd password
expect "*password:" { send "$passwd\n" }
interact

 

###sample 

##remove -P 22 because we meet error :exec: 22: No such file or directory
###add -o stricthostkeychecking=no to 首次登陸時候 提示 avoid Are you sure you want to continue connecting ###(yes/no)?

##remove -P 22 from sftp because we meet error :exec: 22: No such file or directory,Couldn't read packet: ##Connection reset by peer
##in windows nbu master : check security management _ token management : token is MVFNJBPGRJXHCMFU
###check another day token still is MVFNJBPGRJXHCMFU

 


expect <<- EOF
set timeout 5
spawn sftp -o stricthostkeychecking=no useradmin@10.200.1.1

expect {
"(yes/no)?" {send "yes\r"; expect_continue }
"*assword:" {send "user@pass\r"}
}
expect "sftp>"
send "cd /dbsoft/nbusoft/NBU8.1 \r"
expect "sftp>"
send "lcd /tmp/nbu \r"
expect "sftp>"
set timeout -1
send "mget rman.sh \r"
expect "sftp>"
send "mget NetBackup_8.1.2_CLIENTS2.tar.gz \r"
expect "sftp>"
send "mget rman_arc.sh\r"
expect "sftp>"
send "mget mysql_backup.sh\r"
expect "sftp>"
send "mget mysqlbackup_5.7\r"
expect "sftp>"
send "bye\r"
EOF

 

 

因為expect 使用 sftp  可以會存在泄露密碼,安全隱患

 

登錄
ssh免密登錄遠程執行命令/腳本 原創
2018-06-27
5點贊

p7+

碼齡5年

關注
執行一條命令

ssh 192.168.1.12 source /etc/profile
1
執行多條命令(如果有空格,那么需要使用雙引號)

ssh 192.168.222.102 "source /etc/profile;/root/apps/test.sh"
1
執行腳本的坑
通過ssh執行命令,是沒有環境變量的,例如遠程啟動zookeeper。我們知道,zookeeper是需要java環境的支持,但是我們通過ssh啟動其他服務器上的zookeeper時,雖然顯示啟動成功,
但是切換到zookeeper服務器查看進程時,卻發現沒有zookeeper的進程。為什么呢?
我們知道,在/etc/profile中配置JAVA_HOME后需要source /etc/profile后,java環境才生效,而linux重啟后,
即使不手動執行source /etc/profile,java環境也是有效的,這是因為linux在啟動時,已經初始化了/etc/profile文件。
通過ssh遠程執行腳本或命令時,如果執行的東西是需要環境支持的,那么我們必須要先初始化環境。例如:test.sh需要java的支持,並且/etc/profile中配置了java的路徑

ssh 192.168.222.102 "source /etc/profile;/root/apps/test.sh"
1
免密登陸的zookeeper自啟動腳本
#!/bin/bash

SERVERS="pc-server1 pc-server2 pc-server3"
PASSWORD=root

# 自動復制ssh密鑰到相應的主機
auto_ssh_copy_id(){
expect -c "set timeout -1;
spawn ssh-copy-id $1;
expect {
*(yes/no)* {send -- yes\r;exp_continue;}
*assword:* {send -- $2\r;exp_continue;}
eof {exit 0;}
}";
}

ssh_copy_id_to_all(){
for SERVER in $SERVERS
do
auto_ssh_copy_id $SERVER $PASSWORD
done
}

ssh_copy_id_to_all

zk(){
for SERVER in $SERVERS
do
ssh root@$SERVER "source /etc/profile;zkServer.sh $1"
done
}

case $1 in
start)
zk $1
;;
stop)
zk $1
;;
status)
zk $1
;;
*)
echo "Usgae:{start|stop|status}"
esac

 

##sample 因為登錄用戶不是 root,而是 root 權限的ddadmin ,配置ssh 免密登錄,感謝zyp
su - root
ssh-keygen -P ''
ssh-copy-id -i ddadmin@ip

驗證

ssh useradmin@ip

 

 

###sample       目的dep_rman_shell.sh 將文件推送到遠程,同時遠程執行對應腳本,遠程修改主機的rman 腳本

file1: dep_rman_shell.sh

#!/bin/bash
#add more hosts
echo "please make sure config file (rman_shell_config.sh) is ok"
head -n 6 rman_shell_config.sh
echo "please input servers:(10.10.10.10 10.20.20.20.20)"
read SERVERS
echo "SERVERS=$SERVERS"

echo "please input os password:"
read PASSWORD
echo "password=$PASSWORD"

#VIB_FILE="/tmp/nbu/host.tmp"
SHELL_FILE="/dbsoft/nbusoft/NBU8.1/config/shell/rman_shell_config.sh"

#--remove set timeout -1 because it running quickly,have already config have hosts' trust info
vib_shell_copy(){
expect << EOF
set timeout -1
spawn scp -o StrictHostKeyChecking=no $SHELL_FILE useradmin@$1:/tmp/
expect "assword:"
send "$2\r"
expect eof
EOF

}

#--remove set timeout -1 because it running quickly ,have already config have hosts' trust info
vib_install(){

expect << EOF
set timeout -1
spawn ssh -o stricthostkeychecking=no useradmin@$1 "sh /tmp/rman_shell_config.sh"
expect "assword:"
send "$2\r"
expect eof
EOF
}

#--add more password in list ,have already config have trust info
for SER in $SERVERS
#do vib_shell_copy $SER $PASSWORD &> /dev/null
#for PASSWORD in $PASS
do vib_shell_copy $SER $PASSWORD
echo "$SER copy successed"
#vib_install $SER $PASSWORD &> /dev/null
vib_install $SER $PASSWORD
echo "$SER install successed"
done

 

-file 2 rman_shell_config
export sid=ntbs
export user=opntbs
export arch_policy=rman_ntbs_arc
export host=pntbsdb_svc
export ora_policy=rman_ntbsdb

hostname

RSTAT=`ps -ef|grep $user|grep pmon |wc -l`
if [ "$RSTAT" = 0 ]
then

su - $user <<!
cd /usr/openv/netbackup/bin
expect <<- EOF
set timeout 20
spawn ./oracle_link
expect "Do you want to continue? (y/n) \[n\] "
send "y \r"
expect "to make sure the linking process was successful"
EOF
!
echo "install is ok"
else
echo "please check"
fi


cd /usr/openv/netbackup/ext/db_ext/shell
mv sample1 $sid

 

#cd /usr/openv/netbackup/ext/db_ext/shell
#mv sample1 $sid


cd $sid
perl -p -i -e "s/opigfs/$user/g" *.sh
perl -p -i -e "s/pigfsdb01/$host/g" *.sh
perl -p -i -e "s/rman_igfs_arc/$arch_policy/g" *.sh
perl -p -i -e "s/rman_igfs_new/$ora_policy/g" *.sh

 

--file 3 readme

1.first edit config file
2.then sh dep*.sh ,input two ip and password

 

-注意;

上面腳本需要輸入主機密碼,如果信任關系建立好,不需要輸入密碼, 如下命令即可

scp $VIB_FILE $SHELL_FILE useradmin@$1:/backup/suseript/nbu

ssh useradmin@$1 "sh /backup/suseript/nbu/media_config.sh"

 

### sample 3  目的  dep_media.sh 將配置文件host.tmp 傳到對應的機器上,同時運行media_config.sh 將運行一系列命令

 

file 1: dep_media

#!/bin/bash
#add more hosts

echo "please make sure config file (host.tmp) is ok"
echo "make sure all host directroy /backup/suseript/nbu is ok"
head -n 6 host.tmp
echo "please input above info yes/no"
read option
echo "option=$option"
SERVERS="dbsanmd01 dbsanmd02 dbsanmd03 dbsanmd04"
VIB_FILE="/backup/suseript/nbu/host.tmp"
SHELL_FILE="/backup/suseript/nbu/media_config.sh"

#--remove set timeout -1 because it running quickly,have already config have hosts' trust info
vib_shell_copy(){
scp $VIB_FILE $SHELL_FILE useradmin@$1:/backup/suseript/nbu
}

#--remove set timeout -1 because it running quickly ,have already config have hosts' trust info
vib_install(){

ssh useradmin@$1 "sh /backup/suseript/nbu/media_config.sh"

}

#--add more password in list ,have already config have trust info
for SER in $SERVERS
#do vib_shell_copy $SER $PASSWORD &> /dev/null
#for PASSWORD in $PASS
#do vib_shell_copy $SER $PASSWORD
do vib_shell_copy $SER
echo "$SER copy successed"
#vib_install $SER $PASSWORD &> /dev/null
#vib_install $SER $PASSWORD
vib_install $SER
echo "$SER install successed"
done

##for local
sh /backup/suseript/nbu/media_config.sh

 

file2: media_config

hostname
cp /etc/hosts /etc/hosts.bak
/usr/openv/netbackup/bin/bpclntcmd -clear_host_cache
cat /backup/script/nbu/host.tmp >> /etc/hosts
os_name_list=`cat /backup/script/nbu/host.tmp|grep -v "#" |awk ' { print $2 }'`
for os_name in ${os_name_list}
do
echo $os_name
/usr/openv/netbackup/bin/admincmd/bptestbpcd -client $os_name -verbose
done
ls

 

file 3: host.tmp

##202007###

5.6.1.20
db

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM