承接第一部分進(jìn)行總結(jié)分析
我們提供的服務(wù)有:網(wǎng)站建設(shè)、成都網(wǎng)站制作、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、麻江ssl等。為數(shù)千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的麻江網(wǎng)站制作公司
read
-p"prompt" //提示
-ttimeout
給變量默認(rèn)值
varName=${varName:-value}
如果varName不空,則返回varName的值;否則varName會(huì)使用value作為其值
使用read參數(shù)[-p]后,允許在[-p]后面跟一字符串,在字符串后面跟n個(gè)shell變量。n個(gè)shell變量用來(lái)接收從shell界面輸入的字符串
[-p]用法:read –p “string” var1 var2…varn
練習(xí):通過(guò)鍵盤給定一個(gè)文件的路徑,來(lái)判定文件內(nèi)容類型
#!/bin/bash
read –p “Enter a file name:” fileName
type $fileName
通過(guò)鍵盤給定一個(gè)路徑,默認(rèn)為/,來(lái)判定目錄下文件內(nèi)容類型
例如:輸入用戶名,可返回其shell
#!/bin/bash
#
read-p "Plz input a username: " userName
ifid $userName &> /dev/null; then
echo "The shell of $userName is `grep"^$userName\>" /etc/passwd | cut -d: -f7`."
else
echo "No such user. stupid."
Fi
例子:顯示一個(gè)如下菜單給用戶:
cpu)show cpu infomation
mem)show memory infomation
*)quit
1、如果用戶選擇了cpu,則顯示/proc/cpuinfo文件的內(nèi)容;
2、如果用戶選擇了mem,則顯示/proc/meminfo文件的內(nèi)容;
3、退出
#!/bin/bash
#
echo"---------menu----------"
echo"cpu) show cpu infomation"
echo"mem) show memory infomation"
echo"*) quit"
echo"-------menu------------"
read-p "Plz give your choice: " choice
if[ "$choice" == 'cpu' ]; then
cat /proc/cpuinfo
elif[ "$choice" == 'mem' ]; then
cat /proc/meminfo
else
echo "Quit"
exit 3
fi
在第二個(gè)EOF前不要有換行、制表符或者空格
#!/bin/bash
#
cat<< EOF
-------menu------------
cpu)show cpu infomation
mem)show memory infomation
*)quit
-------menu------------
EOF
read-p "Plz give your choice: " choice
if[ "$choice" == 'cpu' ]; then
cat /proc/cpuinfo
elif[ "$choice" == 'mem' ]; then
cat /proc/meminfo
else
echo "Quit"
exit 3
fi
語(yǔ)法:
function F_NAME {
函數(shù)體
}
F_NAME() {
函數(shù)體
}
可調(diào)用:使用函數(shù)名
函數(shù)名出現(xiàn)的地方,會(huì)被自動(dòng)替換為函數(shù);
腳本:
函數(shù)的返回值:
函數(shù)的執(zhí)行結(jié)果返回值:代碼的輸出
函數(shù)中的打印語(yǔ)句:echo, print
函數(shù)中調(diào)用的系統(tǒng)命令執(zhí)行后返回的結(jié)果
執(zhí)行狀態(tài)返回值:
函數(shù)體中最后一次執(zhí)行的命令狀態(tài)結(jié)果
自定函數(shù)執(zhí)行狀態(tài)的返回值:return #
函數(shù)可以接受參數(shù):
在函數(shù)體中調(diào)用函數(shù)參數(shù)的方式同腳本中調(diào)用腳本參數(shù)的方式:位置參數(shù)
$1, $2, ...
$#, $*, $@
示例:服務(wù)腳本示例
#!/bin/bash
#
# chkconfig: 2345 67 34
#
srvName=$(basename $0)
lockFile=/var/lock/subsys/$srvName
start() {
if [ -f $lockFile];then
echo "$srvName is already running."
return 1
else
touch $lockFile
[ $? -eq 0 ] && echo "Starting $srvNameOK."
return 0
fi
}
stop() {
if [ -f $lockFile];then
rm -f $lockFile &> /dev/null
[ $? -eq 0 ] && echo "Stop $srvName OK"&& return 0
else
echo "$srvName is not started."
return 1
fi
}
status() {
if [ -f $lockFile ];then
echo "$srvName is running."
else
echo "$srvName is stopped."
fi
return 0
}
usage() {
echo "Usage:$srvName {start|stop|restart|status}"
return 0
}
case $1 in
start)
start
;;
stop)
stop ;;
restart)
stop
start ;;
status)
status ;;
*)
usage
exit 1 ;;
esac
練習(xí):寫一個(gè)腳本,完成如下功能(使用函數(shù)):
1、提示用戶輸入一個(gè)可執(zhí)行命令;
2、獲取這個(gè)命令所依賴的所有庫(kù)文件(使用ldd命令);
3、復(fù)制命令至/mnt/sysroot/對(duì)應(yīng)的目錄中
解釋:假設(shè),如果復(fù)制的是cat命令,其可執(zhí)行程序的路徑是/bin/cat,那么就要將/bin/cat復(fù)制到/mnt/sysroot/bin/目錄中,如果復(fù)制的是useradd命令,而useradd的可執(zhí)行文件路徑為/usr/sbin/useradd,那么就要將其復(fù)制到/mnt/sysroot/usr/sbin/目錄中;
4、復(fù)制各庫(kù)文件至/mnt/sysroot/對(duì)應(yīng)的目錄中;
#!/bin/bash
#
target=/mnt/sysroot/
[ -d $target ] || mkdir $target
preCommand() {
if which $1 &> /dev/null; then
commandPath=`which--skip-alias $1`
return0
else
echo"No such command."
return1
fi
}
commandCopy() {
commandDir=`dirname $1`
[ -d ${target}${commandDir} ] || mkdir-p ${target}${commandDir}
[ -f ${target}${commandPath} ] || cp $1${target}${commandDir}
}
libCopy() {
for lib in `ldd $1 | egrep -o"/[^[:space:]]+"`; do
libDir=`dirname$lib`
[ -d${target}${libDir} ] || mkdir -p ${target}${libDir}
[ -f${target}${lib} ] || cp $lib ${target}${libDir}
done
}
read -p "Plz enter a command: "command
until [ "$command" == 'quit' ];do
if preCommand $command &>/dev/null; then
commandCopy $commandPath
libCopy $commandPath
fi
read -p "Plz enter a command: "command
done
信號(hào)種類
1) SIGHUP本信號(hào)在用戶終端連接(正?;蚍钦?結(jié)束時(shí)發(fā)出,通常是在終端的控制進(jìn)程結(jié)束時(shí),通知同一session內(nèi)的各個(gè)作業(yè),這時(shí)它們與控制端不再關(guān)聯(lián)。
2) SIGINT程序終止(interrupt)信號(hào),在用戶鍵入INTR字符(通常是Ctrl-C)發(fā)出
3) SIGQUIT和SIGINT類似,但由QUIT字符(通常是Ctrl-/)來(lái)控制。進(jìn)程在因收到SIGQUIT退出時(shí)會(huì)產(chǎn)生core文件,在這個(gè)意義1類似于一個(gè)程序錯(cuò)誤信號(hào)。
4) SIGILL執(zhí)行了非法指令,通常是因?yàn)榭蓤?zhí)行文件本身出現(xiàn)錯(cuò)誤,或者試圖執(zhí)行數(shù)據(jù)段。堆棧溢出時(shí)也有可能產(chǎn)生這個(gè)信號(hào)
trap命令用于在shell程序中捕捉到信號(hào),之后可以有三種反應(yīng)方式:
(1)執(zhí)行一段程序來(lái)處理這一信號(hào)
(2)接受信號(hào)的默認(rèn)操作
(3)忽視這一信號(hào)
trap對(duì)上面三種方式提供了三種基本形式:
第一種形式的trap命令在shell接收到signallist清單中數(shù)值相同的信號(hào)時(shí),將執(zhí)行雙引號(hào)中的命令串。
trap 'commands' signal-list
trap "commands" signal-list
第二種形式的trap命令恢復(fù)信號(hào)的默認(rèn)操作:trap signal-list
第三種形式的trap命令允許忽視信號(hào):trap " " signal-list
trap 'COMMAND' SIGINT(表示關(guān)閉進(jìn)程)
例:寫一個(gè)腳本,能夠ping探測(cè)指定網(wǎng)絡(luò)內(nèi)的所有主機(jī)是否在線,當(dāng)沒(méi)有執(zhí)行完時(shí)可接收ctrl+c命令退出。
#!/bin/bash
quitScript() {
echo "Quit..."
}
trap 'quitScript; exit 5' SIGINT
cnetPing() {
for i in {1..254}; do
if ping -c 1 -W 1 $1.$i &>/dev/null; then
echo "$1.$i is up."
else
echo "$1.$i is down."
fi
done
}
bnetPing() {
for j in {0..255}; do
cnetPing $1.$j
done
}
anetPing() {
for m in {0..255}; do
bnetPing $1.$m
done
}
netType=`echo $1 | cut -d"." -f1`
if [ $netType -ge 1 -a $netType -le 126 ];then
anetPing $netType
elif [ $netType -ge 128 -a $netType -le 191]; then
bnetPing $(echo $1 | cut -d'.' -f1,2)
elif [ $netType -ge 192 -a $netType -le 223]; then
cnetPing $(echo $1 | cut -d'.' -f1-3)
else
echo "Wrong"
exit 2
fi
數(shù)組:連續(xù)的多個(gè)獨(dú)立內(nèi)存空間,每個(gè)內(nèi)存空間相當(dāng)于一個(gè)變量
數(shù)組元素:數(shù)組名+索引(從0開(kāi)始編號(hào))
索引的表示方式:
數(shù)字索引:a[index]
a[0], a[1]
bash 4.0的關(guān)聯(lián)數(shù)組
a[hello], a[hi]
聲明數(shù)組:declare -a ARRAR_NAME
關(guān)聯(lián)數(shù)組:declare -A ARRAY_NAME
支持稀疏格式:僅一維數(shù)組
數(shù)組的賦值:
(1)一次對(duì)一個(gè)元素賦值:
a[0]=$RANDOM
...
echo ${a[0]}
(2)一次對(duì)全部元素賦值:
a=(red blue yellowgreen)
一對(duì)括號(hào)表示是數(shù)組,數(shù)組元素用“空格”符號(hào)分隔開(kāi)。
(3)按索引進(jìn)行賦值:
a=([0]=green [3]=red[2]=blue [6]=yellow)
(4)命令替換:
logs=($(ls /var/log/*.log))
或者logs=(/var/log/*.log)
echo ${logs[0]}
(5)用戶輸入
read -a ARRAY
數(shù)組的訪問(wèn):
用索引訪問(wèn):ARRAY[index]
數(shù)組的長(zhǎng)度:
${#ARRAY[*]}
${#ARRAY[@]}
eg:echo ${#test[*]}
echo ${#test[@]}
練習(xí):寫一個(gè)腳本,生成10個(gè)隨機(jī)數(shù),保存至數(shù)組中;而后顯示數(shù)組下標(biāo)為偶數(shù)的元素;
#!/bin/bash
for i in {0..9};do
num[$i]=$RANDOM
if [ $[$i%2] -eq 0];then
echo "a[i] is${a[i]}"
fi
done
從數(shù)組中挑選某元素:
${ARRAY[@]:offset:number}
切片:
offset:偏移的元素個(gè)數(shù)
number:取出的元素的個(gè)數(shù)
${ARRAY[@]:offset}:取出偏移量后的所有元素
${ARRAY[@]}:取出所有元素
數(shù)組復(fù)制:
要使用${ARRAY[@]}
$@:每個(gè)參數(shù)是一個(gè)獨(dú)立的串
$*:所有參數(shù)是一個(gè)串
向數(shù)組追加元素:非稀疏格式
mylogs,
mylogs[${#week[@]}]
示例:復(fù)制一個(gè)數(shù)組中下標(biāo)為偶數(shù)的元素至一個(gè)新數(shù)組中
#!/bin/bash
declare -a mylogs
logs=(/var/log/*.log)
echo ${logs[@]}
for i in `seq 0 ${#logs[@]}`; do
if [ $[$i%2] -eq 0];then
index=${#mylogs[@]}
mylogs[$index]=${logs[$i]}
fi
done
echo ${mylogs[@]}
從數(shù)組中刪除元素:unset ARRAY[index]
練習(xí)1:生成10個(gè)隨機(jī)數(shù),升序排序
#!/bin/bash
for((i=0;i<10;i++))
do
rnd[$i]=$RANDOM
done
echo -e "total=${#rnd[@]}\n${rnd[@]}\nBegin to sort"
for((i=9;i>=1;i--))
do
for((j=0;j
do
if [ ${rnd[$j]} -gt${rnd[$[$j+1]]} ] ;then
swapValue=${rnd[$j]}
rnd[$j]=${rnd[$[$j+1]]}
rnd[$[$j+1]]=$swapValue
fi
done
done
echo ${rnd[@]}
練習(xí)2:打印九九乘法表
#!/bin/bash
for((i=1;i<=9;i++))
do
strLine=""
for((j=1;i<=9;j++))
do
strLine=$strLine"$i*$j="$[$i*$j]"\t"
[ $i -eq $j ] && echo -e $strLine && break
done
done
字符串切片:
${string:offset:length}
取尾部的指定個(gè)數(shù)的字符:
${string: -length}
取子串:基于模式
${variable#*word}:在variable中存儲(chǔ)字串上,自左而右,查找第一次出現(xiàn)word,刪除字符開(kāi)始至此word處的所有內(nèi)容;
${variable##*word}:在variable中存儲(chǔ)字串上,自左而右,查找最后一次出現(xiàn)word,刪除字符開(kāi)始至此word處的所有內(nèi)容;
file='/var/log/messages'
${file#*/}:返回的結(jié)果是var/log/messages
${file##*/}:返回messages
${variable%word*}:在variable中存儲(chǔ)字串上,自右而左,查找第一次出現(xiàn)word,刪除此word處至字串尾部的所有內(nèi)容;
${variable%%world*}:在variable中存儲(chǔ)字串上,自右而左,查找最后一次出現(xiàn)word,刪除此word處至字串尾部的所有內(nèi)容;
file='/var/log/messages'
${file%*/}:返回的結(jié)果是/var/log
${file%%*/}:返回結(jié)果為空
phonenumber='010-110-8'
${phonenumber%%-*}
${phonenumber##*-}
url="http://www.magedu.com:80"
取端口:${url##*:}
取協(xié)議:${url%%:*}
查找替換:
${variable/pattern/substi}:替換第一次出現(xiàn)
${variable//pattern/substi}:替換所有的出現(xiàn)
${variable/#pattern/substi}:替換行首被pattern匹配到的內(nèi)容
${variable/%pattern/substi}: 行尾
pattern可以使用globbing中的元字符:
*
?
查找刪除:
${variable/pattern}
${variable//pattern}
${variable/#pattern}
${variable/%pattern}
大小寫轉(zhuǎn)換:
小-->大:${variable^^}
大-->?。?{variable,,}
只能對(duì)變量的單個(gè)字符做操作,eg:echo ${user^^a}
變量賦值操作:
${parameter:-word}
Use Default Values. If parameter is unset ornull, the expansion of word is substituted. Otherwise, the value of parameter is
substituted.
${parameter:=word}
Assign Default Values. If parameter is unset or null, the expansionof word is assigned to parameter. Thevalue of parameter is
then substituted. Positional parameters and special parametersmay not be assigned to in this way.
${parameter:?word}
Display Error if Null or Unset. If parameter is null or unset, the expansionof word (or a message to that effect if word is not
present) is written to the standarderror and the shell, if it is not interactive, exits. Otherwise, the value of parameter is
substituted.
${parameter:+word}
Use Alternate Value. If parameter is null or unset, nothing issubstituted, otherwise the expansion of word is substituted.
${variable:-string}
variable為空或未設(shè)定,那么返回string,否則,返回variable變量的值;
${variable:=string}
variable為空或未設(shè)定,則返回string,且將string賦值給變量variable,否則,返回variable的值;
為腳本使用配置文件,并確保某變量有可用值的方式
variable=${variable:-defaultvaule}
eg:
[ -f etc/sysconfig/test ] &&source /etc/sysconfig/test
myvar=${myvar:-www.mageedu.com}
echo $myvar
練習(xí):讀取/etc/sysconfig/network文件,利用其HOSTNAME變量的值設(shè)置主機(jī)名;
9.4 bash編程之補(bǔ)充
mktemp命令:
mktemp [OPTIONS] filename.XXX
-d:創(chuàng)建臨時(shí)目錄
--tmpdir=/path/to/somewhere:指定臨時(shí)文件所在的目錄
mktemp /tmp/tmp.XXX #XXX生成相同數(shù)量隨機(jī)字符
mktemp --tmpdir=/var/tmp tmp.XXX #指定目錄創(chuàng)建臨時(shí)文件
mktemp --tmpdir=/var/tmp -d tmp.XXX #指定目錄創(chuàng)建臨時(shí)目錄
install命令:
install [OPTIONS] SOURCE DEST
install [OPTIONS] SOURCE... DIR
install [OPTIONS] -d DIR ...
增強(qiáng)型的復(fù)制命令:
-o OWNER
-g GROUP
-m MODE
-d :創(chuàng)建目錄
install /etc/fstab /tmp #復(fù)制文件到指定目錄
install --mode=644 /etc/fstab /tmp/ #復(fù)制時(shí)指定權(quán)限
install --owner=scholar /etc/fstab /tmp #復(fù)制時(shí)指定屬主
install --group=scholar /etc/fstab /tmp #復(fù)制時(shí)指定屬組
install -d /tmp/install #創(chuàng)建目錄