scp 上傳文件到多個服務器節點


參考:scp批量上傳文件到多台機器上(升級版)

實測,代碼可運行.

1.如果遇到syntax error near unexpected token問題,基本是由於windows環境下編寫的shell腳本上傳到UNIX中包含了^M引起的。

使用remove_ctrlM.sh替換掉sh腳本中的^M字符,也可以使用 vi -b your_file編輯文件。

如果scp.conf報syntax error near unexpected token問題,則vi -b scp.conf編輯此配置文件,替換掉其中的特殊字符。

2.如果遇到source: not found的異常,查看ubuntu12.04中shell腳本無法使用source的原因及解決方法


原作者的腳本在copy dir的時候,會將整個dir目錄拷貝至 target中,這跟scp命令本身有關。

scp -r ./code/oaf/* huanghongbo@192.168.233.136:$JAVA_TOP會僅拷貝oaf目錄下的文件及文件夾至$JAVA_TOP

但是此處不能用sh multi_scp.sh ./scp.conf ./code/oaf/* $JAVA_TOP,會拋出異常。

所以我針對想僅拷貝目錄下的文件及文件夾做了一點改動。

把multi_scp.sh中的

/usr/bin/expect scp_upload.sh "$ssh_host" "$ssh_port" "$ssh_user" "$ssh_password" "$scp_file" "$scp_target" 

改為了

if [ -d "$scp_file" ]
then
for f in ` ls "$scp_file"`
do
/usr/bin/expect scp_upload.sh "$ssh_host" "$ssh_port" "$ssh_user" "$ssh_password" "$scp_file/$f" "$scp_target"
done
else
#scp file or dir  
/usr/bin/expect scp_upload.sh "$ssh_host" "$ssh_port" "$ssh_user" "$ssh_password" "$scp_file" "$scp_target"
fi

version2,拷貝目錄至target.

version3,僅拷貝目錄下的內容至target.


 

鑒於此種方式需要使用linux的expect模塊,我又寫了一個簡陋的scp,此種方式需要在每次執行scp的時候交互式的輸入scp的密碼,但是特別繁瑣,所以就想到了加入ssh信任免密碼登錄。

Step 1. Linux基礎 - scp免密碼登陸進行遠程文件同步

Step 2. $ sh scp2multi_nodes.sh(下載)

#!/bin/bash
ssh_hosts=("192.168.233.136" "192.168.233.137")
 
default_ssh_user="huanghongbo" 
default_ssh_password="huanghongbo"
default_ssh_port="22"
 
port=$default_ssh_port
scp_file=./code/oaf/
target=$JAVA_TOP
scpuser=$default_ssh_user
 
for((i=0;i<${#ssh_hosts[@]};i++))  
do
#remote ssh host  
scphost=${ssh_hosts[$i]}
echo $i node ,host is $scphost
#echo "["`date +"%F %T"`"] (scp -r $scp_file $ssh_user@$ssh_host:$ssh_port:$scp_target) start" 
 
echo "["`date +"%F %T"`"] (scp -r -P $port $scp_file $scpuser@$scphost:$target  ) start"
#scp -q -r -P $port $scp_file/* $scpuser@$scphost:$target
#-q 不顯示傳輸進度
 
scp -r -P $port $scp_file/* $scpuser@$scphost:$target
 
if [ "$?" -eq "0" ]  
then 
success_hosts="$success_hosts,$scphost" 
else 
fail_hosts="$fail_hosts,$scphost" 
fi 
 
echo "["`date +"%F %T"`"] (scp -r -P $port $scp_file $scpuser@$scphost:$target  ) end"    
 
done  
echo "success_hosts=[$success_hosts]" 
echo "fail_hosts=[$fail_hosts]" 

 

PS:

1.示例中的target都是使用的環境變量$JAVA_TOP,如果remote環境和local環境的$JAVA_TOP環境變量不一致,則會導致傳輸到錯誤的路徑或者scp:***:No such file or directory。

在scp中如何獲取remote環境的環境變量,我暫時還沒找到方法。

看到的一種比較合理的解釋是

How is it supposed to know what the remote variables values are? scp/rcp DO NOT execute a .profile or any login script. They establish a connection to the remote server only.

2.Expect在這個程序里就是用來幫助自動輸入scp的密碼,Expect主要用於把需要人工交互的程序變為程序自動化完成,這個對於運維批量部署系統,批量無人值守安裝,批量執行命令,批量上傳下載
 現代的Shell對程序提供了最小限度的控制(開始,停止,等等),而把交互的特性留給了用戶。 這意味着有些程序,你不能非交互的運行,比如說passwd。 有一些程序可以非交互的運行,但在很大程度上喪失了靈活性,比如說fsck。這表明Unix的工具構造邏輯開始出現問題。Expect恰恰填補了其中的一些裂痕,解決了在Unix環境中長期存在着的一些問題。

default_ssh_user= "huanghongbo" 
default_ssh_password= "huanghongbo"
default_ssh_port= "22"
 
port=$default_ssh_port
scp_file=. /code/oaf/
target=$JAVA_TOP
scpuser=$default_ssh_user
 
for ((i=0;i<${ #ssh_hosts[@]};i++))  
do
#remote ssh host  
scphost=${ssh_hosts[$i]}
echo  $i node ,host is $scphost
#echo "["`date +"%F %T"`"] (scp -r $scp_file $ssh_user@$ssh_host:$ssh_port:$scp_target) start" 
 
echo  "[" ` date  + "%F %T" ` "] (scp -r -P $port $scp_file $scpuser@$scphost:$target  ) start"
#scp -q -r -P $port $scp_file/* $scpuser@$scphost:$target
#-q 不顯示傳輸進度
 
scp  -r -P $port $scp_file/* $scpuser@$scphost:$target
 
if  "$?"  - eq  "0"  ]  
then 
success_hosts= "$success_hosts,$scphost" 
else 
fail_hosts= "$fail_hosts,$scphost" 
fi 
 
echo  "[" ` date  + "%F %T" ` "] (scp -r -P $port $scp_file $scpuser@$scphost:$target  ) end"    
 
done  
echo  "success_hosts=[$success_hosts]" 
echo  "fail_hosts=[$fail_hosts]" 


免責聲明!

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



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