之前也學過一些shell,不過學得並非很深刻,動手寫的代碼的時間也不是不少。前不久將shell比較細的過了一遍,leader佈置了任務讓用shell寫一個腳本將redis源碼壓縮包從一個服務器上傳到另一個服務器,同時在本服務器上傳入命令,解壓源碼包並在另外一個服務器上啓動redis服務。html
雖然學了一些shell,可是本次任務中須要使用的SCP和expect倒是第一次使用,其中也遇到了一些問題,因此在這裏總結一下。linux
現代的Shell對程序提供了最小限度的控制(開始,中止,等等),而把交互的特性留給了用戶。 這意味着有些程序, 你不能非交互的運行,好比說passwd。簡單點說就是你得手動輸入密碼,shell沒有提供給你將密碼直接在程序中一次性搞定的方法。redis
也正是由於如此,expect誕生了。shell
注意expect是獨立於shell以外的,或者說他們徹底不是一個東西(可是二者都是linux下很強大的工具)。當時我由於絕得expect是shell的一個補充,因此在expect中使用了不少shell的語法,呵呵!!!結果你懂的。小程序
我在這裏就簡單說一下我用到的expect的基本語法,以及走過的坑,同時若是你們有願望去學習一下的話我會在後面提供幾個給我很多借鑑的網頁,以便你們深刻學習。centos
3. shell中設置變量,$a="hello world",expect中 set a "hello world" 服務器
4. 在expect中查看變量的值:send_user "$a";ssh
5. 在expect中執行shell的程序: spawn <shellCommand>工具
6. expect中查看傳入的參數的值:[lindex $argv 1] [lindex $argv 2] [lindex $argv 3]...[lindex $argv n]學習
7. 特別有用的:用於進行交互的expect 和 send。我也沒學得太深,只能大概舉一個例子:
spawn ssh -l username 192.168.1.1
expect "*password:"
send "ispass\r"
就差很少這個樣子吧!特別注意的是:send 後面的密碼最後必定要跟一個\r,不然你等着錯吧!!!
恰好到這裏就再說說我遇到的一個大坑——狀況是這樣的,爲了提升代碼的複用性,導師都是讓我不要把什麼密碼啊這一類的寫死的,要麼傳參要麼設置環境變量值,我選擇了傳參的方法,就好比下面這個程序:
hello.sh
#!/usr/bin/env expect
set host [lindex $argv 1]
set passwd [lindex $argv 2]
spawn ssh -l username $host
expect "*password:"
send "$passwd"
執行的命令是這樣的:./hello.sh "192.168.1.1" "ispass\r"
好了,TMD。一直出錯,不記得具體報什麼錯了,好像是提示密碼錯誤。怎麼會出錯呢,糾結,糾結.....足足糾結幾個小時啊!!!不知道錯哪兒了
後來看到了這篇文檔(http://blog.itpub.net/27042095/viewspace-745589/)的第一張圖片,恍然大悟啊!!!趕快改正過來。
hello.sh
#!/usr/bin/env expect
set host [lindex $argv 1]
set passwd [lindex $argv 2]
spawn ssh -l username $host
expect "*password:"
send "$passwd\r"
執行命令:./hello.sh "192.168.1.1" "ispass"
8. 這個必定要注意:若是你在expect中利用ssh登陸了某個服務器,你但願直接進入那個服務器(簡單點說就是你如今是在服務器長操做了,看到的是服務器的文件)必定要使用interact
簡單舉一個例子吧:
#!/usr/bin/expect set timeout 30 spawn ssh -l username 192.168.1.1 expect "password:" send "ispass\r" interact
expect eof
9.程序嘛!仍是儘可能有expect eof 和exit的好一點;
10. 最大的坑來了,expect的if用法:
if { <條件判斷> } { <commands>... } else {
<commands>...
}
也許你沒仔細看,我來提醒你一下:
你造上面紅色框框起來的部分必須在一行嗎?並且彼此之間是必須有空格分隔的。唉,當時這個問題,都快把本身調試哭了!!!
有了上面的語法,你們簡單編輯一個小程序已經夠了!!!至少完成個人任務我只用到了上面的語法,若是你們想比較深刻的學習,下面的幾個網站值得一看呢!!!
很淺的語法:http://www.cnblogs.com/arlenhou/p/learn_expect.html
例子雖短,但給我比較多啓發的一個網站:https://www.centos.bz/tag/expect/
expect學習筆記及實例詳解(真的不錯) :http://blog.itpub.net/27042095/viewspace-745589/
Expect 教程中文版:http://fanqiang.chinaunix.net/a4/b8/20010912/1000001278.html
scp的語法是簡單又實用,原本還想講一下的。不過實在感受下面這篇文檔已經太棒了,因此這裏直接給個鏈接吧!!!
SCP 命令:http://www.cnblogs.com/hitwtx/archive/2011/11/16/2251254.html
最後須要提一下的是,本程序中用到了利用ssh控制遠程服務器執行命令的方法:
ssh <username>@<host> "<command1>;<command2>...<command3>"
如:ssh zhangsan@192.168.1.1 "cd /home;ls -l"
注意兩個點:
一、雙引號,必須有。若是不加雙引號,第二個ls命令在本地執行;
二、分號,兩個命令之間用分號隔開。