如何定義函數(/etc/init.d下有個系統內定functions)
function: function name { COMMANDS ; } or name () { COMMANDS ; }
Define shell function.
Create a shell function named NAME. When invoked as a simple command,
NAME runs COMMANDs in the calling shell's context. When NAME is invoked,
the arguments are passed to the function as $1...$n, and the function's
name is in $FUNCNAME.
Exit Status:
Returns success unless NAME is readonly.
語法一:
f_name (){
...函數體...
}
語法二:
function f_name {
...函數體...
}
語法三:
function f_name () {
...函數體...
}
定義函數和調用函數
單獨寫一個腳本functions,內部定義需要用到的函數,用的時候直接在新的shell中source functions。
示例
functions
func1 () {
echo func1
local name=mage----------》函數內的變量儘量定義成本地變量,防止腳本調用該函數時,腳本內有變量名稱和函數內的變量名稱一樣,造成變量污染
return 10---------》返回調用此函數的腳本中,其後可帶NUM,用於$?的判斷。在return下面的命令不予執行。
}
func2 () {
echo func2
}diaoyonn.sh
#!/bin/bash
source functions
name=wang
echo diaoyong.sh $name
func1
echo diaoyong.sh $name
/etc/init.d/functions內部有很多函數,用的時候需要重新source該文件,其中有個action函數,是啓動或關閉服務右邊的[ ok ]顯示。
信號捕捉trap
進程收到系統發出的指定信號後,將執行自定義指令,而不會執行原操作
trap '觸發指令' 信號
忽略信號的操作
trap '' 信號
恢復原信號的操作
trap '-' 信號
列出自定義信號操作
trap -p
當腳本退出時,執行finish函數
trap finish EXIT
示例:捕捉kill裏的信號 int=ctrl+c
#!/bin/bash
trap 'echo “signal:SIGINT"' int
trap -p
for((i=0;i<=10;i++))
do
sleep 1
echo $i
done
trap '' int
trap -p
for((i=11;i<=20;i++))
do
sleep 1
echo $i
done
trap '-' int
trap -p
for((i=21;i<=30;i++))
do
sleep 1
echo $i
done
數組
數組:存儲多個元素的連續的內存空間,相當於多個變量的集合
數組名和索引
索引:編號從0開始,屬於數值索引
注意:索引可支持使用自定義的格式,而不僅是數值格式,即爲關聯索引,bash4.0版本之後開始支持
bash的數組支持稀疏格式(索引不連續)
聲明數組:
declare -a ARRAY_NAME 定義數組爲數字標識從0開始,支持跳躍 默認不定義爲數字標識
declare -A ARRAY_NAME 關聯數組 定義數組爲關聯數組 自定義標識
注意:兩者不可相互轉換
數組賦值
數組元素的賦值(數組支持{}展開,如name=({1..10}))引用時可以echo ${name=[0]},打印數組的第一個變量值
(1) 一次只賦值一個元素
ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"
(2) 一次賦值全部元素
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
name=("zhangsna" "lisi" "wangwu")
(3) 只賦值特定元素
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
name=([0]="zhangsna" [2]="lisi" [4]="wangwu")
(4) 交互式數組值對賦值(如不定義此項,則表示用數字標識爲角標,否則使用abc)
read -a ARRAY
declare -A name
name=([a]="zhangsna" [c]="lisi" [d]="wangwu")
顯示所有數組:
declare -a
引用數組
引用數組元素
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下標爲0的元素
引用數組所有元素
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
數組的長度(數組中元素的個數)
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
刪除數組中的某元素:導致稀疏格式
unset ARRAY[INDEX]
刪除整個數組
unset ARRAY
數組數據處理
引用數組中的元素:
數組切片:
${ARRAY[@]:offset:number}
offset 要跳過的元素個數
number 要取出的元素個數
取偏移量之後的所有元素
${ARRAY[@]:offset}
向數組中追加元素:
ARRAY[${#ARRAY[*]}]=value
name[${#name[@]}]=7
關聯數組:
declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)
注意:關聯數組必須先聲明再調用
字符串切片
${#var}:返回字符串變量var的長度
${var:offset}:返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,到最後的部分,offset的取值在0 到 ${#var}-1 之間(bash4.2後,允許爲負值)
${var:offset:number}:返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,長度爲number的部分
${var: -length}:取字符串的最右側幾個字符
注意:冒號後必須有一空白字符
${var:offset:-length}:從最左側跳過offset字符,一直向右取到距離最右側lengh個字符之前的內容
${var: -length:-offset}:先從最右側向左取到length個字符開始,再向右取到距離最右側offset個字符之間的內容
注意:-length前空格
字符串處理
基於模式取子串
${var#*word}:其中word可以是指定的任意字符
功能:自左而右,查找var變量所存儲的字符串中,第一次出現的word, 刪除字符串開頭至第一次出現word字符串(含)之間的所有字符
${var##*word}:同上,貪婪模式,不同的是,刪除的是字符串開頭至最後一次由word指定的字符之間的所有內容
示例:
file=“var/log/messages”
${file#*/}: log/messages
${file##*/}: messages
${var%word*}:其中word可以是指定的任意字符
功能:自右而左,查找var變量所存儲的字符串中,第一次出現的word, 刪除字符串最後一個字符向左至第一次出現word字符串(含)之間的所有字符
file="/var/log/messages"
${file%/*}: /var/log
${var%%word*}:同上,只不過刪除字符串最右側的字符向左至最後一次出現word字符之間的所有字符
示例:
url=http://www.magedu.com:80
${url##*:} 80
${url%%:*} http
查找替換
${var/pattern/substr}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替換之
${var//pattern/substr}: 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替換之
${var/#pattern/substr}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替換之
${var/%pattern/substr}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替換之
查找並刪除
${var/pattern}:刪除var表示的字符串中第一次被pattern匹配到的字符串
${var//pattern}:刪除var表示的字符串中所有被pattern匹配到的字符串
${var/#pattern}:刪除var表示的字符串中所有以pattern爲行首匹配到的字符串
${var/%pattern}:刪除var所表示的字符串中所有以pattern爲行尾所匹配到的字符串
字符大小寫轉換
${var^^}:把var中的所有小寫字母轉換爲大寫
${var,,}:把var中的所有大寫字母轉換爲小寫
變量賦值
高級變量用法-有類型變量
Shell變量一般是無類型的,但是bash Shell提供了declare和typeset兩個命令用於指定變量的類型,兩個命令是等價的
declare [選項] 變量名
-r 聲明或顯示只讀變量
-i 將變量定義爲整型數
-a 將變量定義爲數組
-A 將變量定義爲關聯數組
-f 顯示已定義的所有函數名及其內容
-F 僅顯示已定義的所有函數名
-x 聲明或顯示環境變量和函數
-l 聲明變量爲小寫字母 declare –l var=UPPER
-u 聲明變量爲大寫字母 declare –u var=lower
eval命令
eval命令將會首先掃描命令行進行所有的置換,然後再執行該命令。該命令適用於那些一次掃描無法實現其功能的變量.該命令對變量進行兩次掃描
示例:
[root@server ~]# CMD=whoami
[root@server ~]# echo $CMD
whoami
[root@server ~]# eval $CMD
root
[root@server ~]# n=10
[root@server ~]# echo {0..$n}
{0..10}
[root@server ~]# eval echo {0..$n}
0 1 2 3 4 5 6 7 8 9 10
間接變量引用
如果第一個變量的值是第二個變量的名字,從第一個變量引用第二個變量的值就稱爲間接變量引用
variable1的值是variable2,而variable2又是變量名,variable2的值爲value,間接變量引用是指通過variable1獲得變量值value的行爲
variable1=variable2
variable2=value
bash Shell提供了兩種格式實現間接變量引用
eval tempvar=\$$variable1
tempvar=${!variable1}
示例:
[root@server ~]# N=NAME
[root@server ~]# NAME=wangxiaochun
[root@server ~]# N1=${!N}
[root@server ~]# echo $N1
wangxiaochun
[root@server ~]# eval N2=\$$N
[root@server ~]# echo $N2
wangxiaochun
創建臨時文件
mktemp命令:創建並顯示臨時文件,可避免衝突
mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filenameXXX
X至少要出現三個
OPTION:
-d: 創建臨時目錄
-p DIR或--tmpdir=DIR:指明臨時文件所存放目錄位置
示例:
mktemp /tmp/testXXX
tmpdir=`mktemp –d /tmp/testdirXXX`
mktemp --tmpdir=/testdir testXXXXXX
安裝複製文件
install命令:
install [OPTION]... [-T] SOURCE DEST 單文件
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...創建空目錄
選項:
-m MODE,默認755
-o OWNER
-g GROUP
示例:
install -m 700 -o wang -g admins srcfile desfile
install –m 770 –d /testdir/installdir
expect介紹
expect 是由Don Libes基於Tcl( Tool Command Language )語言開發的,主要應用於自動化交互式操作的場景,藉助 expect 處理交互的命令,可以將交互過程如:ssh登錄,ftp登錄等寫在一個腳本上,使之自動化完成。尤其適用於需要對多臺服務器執行相同操作的環境中,可以大大提高系統管理人員的工作效率
expect命令
expect 語法:
expect [選項] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
選項
-c:從命令行執行expect腳本,默認expect是交互地執行的
示例:expect -c 'expect "\n" {send "pressed enter\n"}
-d:可以輸出輸出調試信息
示例:expect -d ssh.exp
expect中相關命令
spawn 啓動新的進程
send 用於向進程發送字符串
expect 從進程接收字符串
interact 允許用戶交互
exp_continue 匹配多個字符串在執行動作後加此命令
expect
expect最常用的語法(tcl語言:模式-動作)
單一分支模式語法:
expect “hi” {send “You said hi\n"}
匹配到hi後,會輸出“you said hi”,並換行
多分支模式語法:
expect "hi" { send "You said hi\n" } \
"hehe" { send "Hehe yourself\n" } \
"bye" { send "Good bye\n" }
匹配hi,hello,bye任意字符串時,執行相應輸出。等同如下:
expect {
"hi" { send "You said hi\n"}
"hehe" { send "Hehe yourself\n"}
"bye" { send " Good bye\n"}
}
示例
#!/usr/bin/expect
spawn scp /etc/fstab 192.168.8.100:/app
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
expect eof
#!/usr/bin/expect
spawn ssh 192.168.8.100
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
interact
#expect eof
示例:變量
#!/usr/bin/expect
set ip 192.168.8.100
set user root
set password magedu
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
#./ssh3.exp 192.168.8.100 root magedu
示例:執行多個命令
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd haha\n" }
expect "]#" { send "echo magedu |passwd --stdin haha\n" }
send "exit\n"
expect eof
#./ssh4.exp 192.168.8.100 root magedu
示例:shell腳本調用expect
#!/bin/bash
ip=$1
user=$2
password=$3
expect <<EOF
set timeout 20
spawn ssh $user@$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