工作中經常需要把一些文件從一個服務器傳輸到另一台服務器,linux環境下最習慣的方式當然是scp,但是scp需要交互輸入密碼有時候覺得麻煩,記錄幾種無需手動輸入密碼的方法。
方法一:建立SSH互信
此方式不僅是方便scp,在可靠系統間此方式也是非常方便的連接方式,具體建立互信操作過程暫略,前面地方有單獨記錄過了。
方法二:使用sshpass工具
建立信任關系的做法是最方便和安全的做法,但是在有些場景下(比如遠端的authorized_keys是不能隨意更改的),那么這個時候我們就可以借助sshpass這個第三方工具來完成ssh連接時的密碼輸入。先看一下sshpass的man手冊中是如何描述的:
sshpass - noninteractive ssh password provider
從描述上就可以清晰的了解到,sshpass的設計就是為了使用非交互的場景下輸入ssh連接的密碼。
sshpass的使用比較簡單,先看一下幫助文檔:
root@localhost:~# sshpass
Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters
-f filename Take password to use from file
-d number Use number as file descriptor for getting password
-p password Provide password as argument (security unwise)
-e Password is passed as env-var "SSHPASS"
With no parameters - password will be taken from stdin
-h Show help (this screen)
-V Print version information
At most one of -f, -d, -p or -e should be used
其中-p是直接指定密碼,-f是從文件中讀取密碼。那么一個使用sshpass的簡單例子就是:
[root@node1 ~]# sshpass -f pa.txt scp index root@192.168.10.22:/var
[root@node1 ~]# sshpass -p root1234 scp config.log root@192.168.10.22:/root/a.lo
使用sshpass的好處就是方便直接,無需了解公私鑰、加密認證等相關知識,簡單易懂;但是使用sshpass最大的壞處就是在使用時會涉及到明文密碼,大大降低了安全性。
方式三:使用expect腳本來輸入密碼
expect用於自動化地執行linux環境下的命令行交互任務,例如scp、ssh之類需要用戶手動輸入密碼然后確認的任務。有了這個工具,定義在scp過程中可能遇到的情況,然后編寫相應的處理語句,就可以自動地完成scp操作了。
下面就是一個使用expect來完成scp時無需輸入密碼的腳本:
#!/usr/bin/expect set timeout 10 set host [lindex $argv 0] set username [lindex $argv 1] set password [lindex $argv 2] set src_file [lindex $argv 3] set dest_file [lindex $argv 4] spawn scp $src_file $username@$host:$dest_file expect { "(yes/no)?" { send "yes\n" expect "*assword:" { send "$password\n"} } "*assword:" { send "$password\n" } } expect "100%" expect eof
意代碼剛開始的第一行,指定了expect的路徑,與shell腳本相同,這一句指定了程序在執行時到哪里去尋找相應的啟動程序。代碼剛開始還設定了timeout的時間為10秒,如果在執行scp任務時遇到了代碼中沒有指定的異常,則在等待10秒后該腳本的執行會自動終止。
從以上代碼剛開始的幾行可以看出,我為這個腳本設置了5個需要手動輸入的參數,分別為:目標主機的IP、用戶名、密碼、本地文件路徑、目標主機中的文件路徑。如果將以上腳本保存為expect_scp文件,則在shell下執行時需要按以下的規范來輸入命令:
./expect_scp 192.168.10.21 root 123456 /root/src_file /root/dest_file
以上的命令執行后,將把本地/root目錄下的src_file文件拷貝到用戶名為root,密碼為123456的主機192.168.10.21中的/root下,同時還將這個源文件重命名為dest_file。
spawn代表在本地終端執行的語句,在該語句開始執行后,expect開始捕獲終端的輸出信息,然后做出對應的操作。expect代碼中的捕獲的(yes/no)內容用於完成第一次訪問目標主機時保存密鑰的操作。有了這一句,scp的任務減少了中斷的情況。代碼結尾的expect eof與spawn對應,表示捕獲終端輸出信息的終止。
使用expect需要了解的一點是:用expect速度會比較慢,因為需要等待返回的數據,然后輸入命令執行,沒有ssh密鑰登錄的快速。
安全性和速度上考慮建立信任關系都是最佳的方法,至於在具體的環境中選擇什么根據實際情況來選擇。