1. 程式人生 > >函數及expect

函數及expect

函數 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