shell指令碼實現scp上傳(expect互動)及ftp上傳,scpexpect
最近有兩個需求,一個是每天定時從各個伺服器下拷貝檔案到一台掛有大磁碟的伺服器,把每台伺服器的檔案區分拷貝過去並刪除本伺服器的檔案。
第二個需求是把掛有大磁碟的伺服器上備份的檔案通過ftp傳送出去。(不要問我為啥不直接從各個伺服器通過ftp傳出去而要繞一層掛有大磁碟的伺服器,因為ftp提供的太晚了。做第一個需求的時候還沒有第二個需求)
本來是做java開發的,但是公司沒有伺服器營運人員,所以自己什麼都要解決。研究了下shell指令碼的scp命令,最初的方案是把shell指令碼和scp互動分開,然後在主指令碼裡邊調用scp的互動指令碼,最後無意間發現shell竟然有EOF這個功能(別笑,本人linux除了正常的操作和查詢基本上沒研究)廢話不說,直接上指令碼,做個記錄。
expect互動需要安裝對應的軟體。tcl8.4.11-src expect5.45
指令碼一:
定時從指定目錄拷貝到另一台伺服器的指定目錄,拷貝成功刪除本地的檔案。
#!/bin/bash#owner huiyunfeiNOW_TIME=`date '+%Y-%m-%d %H:%M:%S'`echo "$NOW_TIME begin start backup.sh"FROM_DIR=/data/imageTAR_DIR=/data/tempLAST_DATE=$(date -d last-day +%Y%m%d)cd $FROM_DIRif [ ! -d "$FROM_DIR/$LAST_DATE" ]; then echo "$NOW_TIME $LAST_DATE dir is not exist,begin exit"exit fi if [ ! -f "$TAR_DIR/$LAST_DATE.tar.gz" ]; thentar -zcf $TAR_DIR/$LAST_DATE.tar.gz $LAST_DATE/echo "tar $LAST_DATE.tar.gz success"elseecho "tar $LAST_DATE.tar.gz is exist"fiTO_HOST="172.19.75.191"USER="root"PASSWD="Shhz123654*"TO_DIR="/date/188/"/usr/expect/bin/expect <<-EOFset timeout -1spawn scp -o "StrictHostKeyChecking no" $TAR_DIR/$LAST_DATE.tar.gz $USER@$TO_HOST:$TO_DIRexpect "assword:"send "$PASSWD\n"expect "100%"expect eofEOFecho "scp $TO_HOST success"rm -rf $FROM_DIR/$LAST_DATErm -rf $TAR_DIR/$LAST_DATE.tar.gzecho "rm dir,dir.tar.gz success"echo "$NOW_TIME stop backup.sh"
第二個指令碼描述的比較詳細。
#!/bin/bash#owner huiyunfei#2018-01-24##目標:#本地檔案夾/test1 /test2 /test3 都會有昨天的tar.gz #例:/test1/20180123.tar.gz /test2/20180123.tar.gz /test3/20180123.tar.gz#上傳到ftp data/test1 data/test2 data/test3#並產生對應的總上傳日誌記錄 ftp_run_log,上傳的同時如果出錯要產生對應檔案的error.log並退出指令碼#上傳出錯會sleep3分鐘並迴圈三次,如果三次內成功則刪除對應的error.log,本地的tar.gz並繼續上傳下一個#總任務完成後刪除本地檔案夾下對應的檔案,退出指令碼#指令碼放環境需要修改以下地方:#ftp_run_log 總任務日誌記錄#ftp_err_dir 單個檔案夾錯誤記錄檔記錄(迴圈三次成功則會被刪除)#local_file_dir 本地待上傳檔案所在子檔案夾#ftp_file_dir ftp待儲存子檔案夾#server_arr 待上傳資料夾清單#ftp_ip #ftp_user ftp_passwd#ftp_run_log='/home/yunfei/logs/ftprunlogs/cron_ftp_run.log'ftp_err_dir="/home/yunfei/logs/temperrorlogs/"echo "`date +%F" "%T":"%N` Script : $0 start runing..." >> ${ftp_run_log}t_last_day=`date -d last-day +%Y%m%d`put_file_name="${t_last_day}.tar.gz" #昨天的檔案 20180123ftp_ip=116.62.175.185ftp_user=yingjieftpftp_passwd=yingjiesftp###########################FTP自動化上傳函數 有錯誤就return1send_file(){ ftp -i -n ${ftp_ip} 21 2>$3 << _EOF_ user ${ftp_user} ${ftp_passwd} passive bin lcd $1 cd $2 put ${put_file_name} bye_EOF_ #統計前面FTP運行輸出的錯誤記錄檔記錄行數 log_count=`cat $3|wc -l` [ ${log_count} -eq 0 ] && return 0 || return 1} ###########################調用FTP上傳函數,返回until需要的狀態值#每次錯誤睡眠120秒,總迴圈三次function run_send_file(){ send_file $1 $2 $3 if [ $? -eq 0 ];then echo "`date +%F" "%T":"%N` Send : $5_${put_file_name} to ftp_server was successfully." >> ${ftp_run_log} return 0 else echo "`date +%F" "%T":"%N` Send : $5_${put_file_name} more than $4 time." >> ${ftp_run_log} sleep 120 return 1 fi} ###########################迴圈操作每個檔案夾的檔案handle(){ local_file_dir="/home/yunfei/data/$1/" ftp_file_dir="/test/$1" ftp_err_log="${ftp_err_dir}$1_${put_file_name}_error.log" #如果某個檔案夾或者檔案夾內不存在對應的tar.gz直接進行下一個檔案夾 if [ ! -d ${local_file_dir} ]; then echo "${local_file_dir} dir is not exist,begin next..." >> ${ftp_run_log} return fi if [ ! -f ${local_file_dir}${put_file_name} ]; then echo "${put_file_name} file is not exist,begin next..." >> ${ftp_run_log} return fi #出錯則迴圈3次,總共6分鐘 x=1 i=1 until [ "$i" -eq 0 ];do [ $x -gt 3 ] && { echo "`date +%F" "%T":"%N` Send : $1_${put_file_name} to ftp_server was failed, Please check..." >> ${ftp_run_log} exit } run_send_file ${local_file_dir} ${ftp_file_dir} ${ftp_err_log} $x $1 i=`echo $?` x=`expr $x + 1` done #刪除FTP產生的臨時錯誤記錄檔檔案 [ -f ${ftp_err_log} ] && rm ${ftp_err_log} #刪除本機資料 #rm -rf ${local_file_dir}${put_file_name}}server_arr=("187" "188" "189" ) for server in ${server_arr[@]}; do handle $server;doneecho "`date +%F" "%T":"%N` Script : $0 done." >> ${ftp_run_log}