函數及expect
在寫腳本的時候,會經常用到某些算法、命令集等,如果每次都要重新再寫一遍,就非常浪費時間,所以就需要用到函數來解決這個問題了。而且有時候會遇到交互式的情況,那麽該怎麽辦呢?except就是用來解決這種情況的。那麽接下來就看一下函數及expect的用法吧。
一、函數
1、定義函數的定義:
f_name()
{
...函數體...
}
2、函數體:
函數體就是一堆命令的集合
3、函數的調用:
直接寫函數名就是調用該函數
4、函數的刪除:
unset f_name
函數說明:
1、函數function是由若幹條shell命令組成的語句塊,實現代碼重用和模塊化編程。
2、它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一部分
3、函數和shell程序比較相似,區別在於:
Shell程序在子Shell中運行,不會影響父shell。
而函數在當前Shell中運行。因此在當前Shell中,函數可以對shell中變量進行修改。
比如當前shell中變量name的值是chen,而在函數中定義name=li,那麽調用函數之後,當前shell中name的值就變成li了
註意:如果函數體與{}寫在同一行,那麽大括號裏兩邊都要有空格,且最後的空格之前要有分號。
4、local 變量名
表示設置本地變量,只在函數體內部起作用
比如,當前shell中name的值為li,而在函數中定義local name=chen,那麽不影響當前shell
5、在命令行定義好的函數是不能修改的,只能刪除重建,或者直接使用同一個函數名,重新寫函數體 ,那麽就會覆蓋原來的函數體了。
6、函數名不要跟現有的別名,現有的命令等沖突。如果沖突,系統會認為你是要執行該命令,而不是定義函數,就會報錯
7、函數相當於命令,可以使用反引號``來引用其執行結果
8、函數如果是在命令行直接寫的,那麽只在當前終端能用,如果寫在文件中,那麽都可以用
9、函數中可以使用別名,腳本中不能用別名
10、在函數中一般不用exit退出,會直接退出當前shell,可以使用return退出函數,並且還可以自定義返回值。
11、/etc/init.d/functions該文件存放著大量的函數的定義
如果別的函數或者腳本需要用到該文件裏的函數,那麽直接使用. /etc/init.d/functions調用這個文件,再調用其中的函數即可。當然自定義的函數也可以寫入其中,或者自己再建一個文件存放自定義的函數,那麽用的時候直接調用文件,就不用每次都要定義函數了。
12、函數的遞歸調用,即自己調用自己。每調用一次就開一個子進程,所以使用函數的時候註意遞歸次數。
了解了函數的作與用法之後,來寫個腳本試試吧
編寫腳本/root/bin/copycmd.sh,要求:
(1) 提示用戶輸入一個可執行命令名稱
(2) 獲取此命令所依賴到的所有庫文件列表
(3) 復制命令至某目標目錄(例如/mnt/sysroot)下的對應路徑下;如:
/bin/bash ==> /mnt/sysroot/bin/bash
/usr/bin/passwd==> /mnt/sysroot/usr/bin/passwd
(4) 復制此命令依賴到的所有庫文件至目標目錄下的對應路徑下:如:
/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
(5)每次復制完成一個命令後,不要退出,而是提示用戶鍵入新的要復制的命令,並重復完成上述功能;直到用戶輸入quit
#!/bin/bash
. /etc/init.d/functions
echo "目標目錄是:/app"
[ -d /app ]||mkdir /app
cpcmd(){
if which $needcmd &>/dev/null;then
local cmd=`which --skip-alias $needcmd`
local dir=`dirname $cmd`
[ -d /app$dir ]||mkdir -p /app$dir
if [ -f /app$cmd ];then
echo "$cmd 已存在"
else
cp $cmd /app$dir&&echo `action "$cmd" true`
fi
elif [ "$needcmd" == "quit" ];then
exit
else
echo "命令不存在或者該命令是內部命令或者該命令是別名"
fi
}
cpso(){
if which $needcmd &>/dev/null;then
local so=`ldd $(which --skip-alias $needcmd)|egrep -o "/.* "`
for i in $so ;do
local sodir=`dirname $i`
[ -d /app$sodir ]||mkdir -p /app$sodir
if [ -f /app$i ];then
echo "$i 已存在"
else
cp $i /app$sodir&&echo `action "$cmd" true`
fi
done
fi
}
until [[ "$needcmd" == "quit" ]];do
read -p "請輸入需要復制的命令(quit退出): " needcmd
cpcmd
cpso
done
二、expect
expect默認是沒有安裝的,需要安裝yum install expect
1、expect作用:
自動化地把交互式的提交變成非交互式的。
可以將交互過程如:ssh登錄,ftp登錄等寫在一個腳本上,使之自動化完成。尤其適用於需要對多臺服務器執行相同操作的環境中,可以大大提高系統管理人員的工作效率
2、expect 語法:
expect [選項] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
選項:
-c:從命令行執行expect腳本,默認expect是交互地執行的
示例:expect -c ‘expect "hi" {send "you said hi\n"}‘
-d:可以輸出調試信息,即顯示詳細的過程
比如expect -d ssh1.exp表示執行ssh1.exp登陸到別的終端,並且顯示詳細的信息。而且登陸之後,在該終端執行的每個操作都會重新再顯示一遍。
3、expect中相關命令
spawn:啟動新的進程
send:用於向進程發送字符串
expect:從進程接收字符串
interact:允許用戶交互
exp_continue 需要匹配多個字符串時,在執行動作後加此命令
這幾個命令會在下面的示例中詳細說明
4、expect最常用的語法(tcl語言:模式-動作)單一分支模式語法:
比如expect “hi” {send “You said hi\n"}
表示匹配到hi後,會輸出“you said hi”,並換行
5、多分支模式語法:
比如expect
expect "hi" { send "You said hi\n" } \
"hehe" { send “Hehe yourself\n" } \
"bye" { send “Good bye\n" }
表示匹配hi,hello,bye任意字符串時,執行相應輸出。
示例1:
cat ssh1.exp
#!/usr/bin/expect
spawn ssh 192.168.80.128 ----->表示啟動新進程,即執行ssh命令
expect {
"yes/no" { send "yes\n";exp_continue } ---->表示匹配到yes/no時,就輸入yes並
回車,exp_continue表示後面還有字符串需要匹配
"password" { send "123456\n" } ---->表示匹配到password時,就輸入123456並回車
}
Interact ----->允許用戶交互,也就是說成功登陸之後可以繼續在該終端 繼續操作,而不直接退出
執行:ssh1.exp
示例2:在expect腳本使用變量
cat ssh2.exp
#!/usr/bin/expect
set ip 192.168.8.100 ----->設置變量ip=192.168.8.100
set user root ---->設置變量user=root
set password 123456 ---->設置變量password=123456
set timeout 10 ----->設置超時時間為10秒,超過10秒沒執行成功就終止進程
spawn ssh [email protected]$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
Interact
執行:ssh2.exp
示例3:引用位置參數
cat ssh3.exp
#!/usr/bin/expect
set ip [lindex $argv 0] ----->將第一個參數的值賦值給變量ip
set user [lindex $argv 1] ----->將第二個參數的值賦值給變量user
set password [lindex $argv 2] ----->將第三個參數的值賦值給變量password
spawn ssh [email protected]$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
執行:ssh3.exp 192.168.80.128 root 123456
示例4:執行多個命令
cat ssh4.exp
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 10
spawn ssh [email protected]$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd haha\n" } ----->創建用戶haha
expect "]#" { send "echo magedu |passwd --stdin haha\n" }----->給該用戶設置密碼
send "exit\n" ----->退出連接
expect eof ------>結束expect,相當於退出ssh連接後換行的作用
執行:ssh4.exp 192.168.80.128 root 123456
示例5:shell腳本調用expect
cat ssh5.sh
#!/bin/bash
ip=$1
user=$2
password=$3
expect <<EOF ------->將下面的內容重定向到expect,直到讀到EOF結束
set timeout 10
spawn ssh [email protected]$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd hehe\n" }
expect "]#" { send "echo magedu |passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
執行:ssh5.sh 192.168.8.100 root magedu
以上就是博主要跟大家分享的東西,希望能對大家有所幫助。歡迎留言,共同探討。
函數及expect