單分支if語句:
if 條件; then
語句1
語句2
...
fi
if 條件
then
例子1:寫一個腳本,實作如下功能:
如果使用者存在,就說明其存在;
#!/bin/bash
#
UserName=user1
if grep "^$UserName\>" /etc/passwd &> /dev/null; then
echo "$UserName exists."
if id $UserName &> /dev/null; then
練習:寫一個腳本,實作如下功能:
如果用存在,就顯示其UID和SHELL;
grep "^$UserName\>" /etc/passwd | cut -d: -f3,7
如果裝置/dev/sda3已經挂載,就顯示其挂載點;
Device='/dev/sda3'
if mount | grep "^$Device" &> /dev/null; then
mount | grep "/dev/sda3" | cut -d' ' -f3
如果/etc/rc.d/rc.sysinit中有空白行,就顯示其空白行數;
File='/etc/rc.d/rc.sysinit'
if grep "^$" $File &> /dev/null; then
grep "^$" $File | wc -l
雙分支if語句:
語句1
語句2
...
else
例子:寫一個腳本:
如果指定的使用者存,先說明其已經存在,并顯示其ID号和SHELL;否則,就添加使用者,并顯示其ID号;
如果裝置/dev/sda3已經挂載,就顯示其挂載點;否則,就說明其未挂載或裝置不存在;
echo "$Device not mounted or not exist."
bash條件測試:
[ expression ]
` expression `
test expression
整數測試
字元測試
檔案測試
整數測試:
expression: 數值1 比較符号 數值2
$A 比較符号 $B
大于:-gt, 例如 $A -gt $B
大于或等于:-ge
等于:-eq
小于:-lt
小于或等于:-le
不等于:-ne
例子:寫一個腳本,生成兩個随機數,比較其大小;顯示大數;
bash有個内置變量:$RANDOM
A=$RANDOM
B=$RANDOM
if [ $A -ge $B ]; then
echo "Max number is $A."
echo "Max number is $B."
練習:寫一腳本,随機生成一個整數,判定,顯示其奇偶性;
if [ $[$A%2] -eq 0 ]; then
echo "$A: Even"
echo "$A: Odd"
練習:給定一個使用者,如果其ID号大于499,就說明其是普通使用者,否則,就說明其是管理者或系統使用者;
UserName=daemon
Uid=`id -u $UserName`
if [ $Uid -gt 499 ]; then
echo "A common user: $UserName."
echo "admin user or system user: $UserName."
練習:求200以内所有為3的整數倍的整數之和;
Sum=0
for I in {1..200}; do
if [ $[$I%3] -eq 0 ]; then
Sum=$[$Sum+$I]
fi
done
echo "Sum: $Sum."
練習:給定一個使用者,如果其UID等于GID,就說明這是個“good guy”,否則,“Bad guy.”
if [ `id -u $UserName` -eq `id -g $UserName` ]; then
echo "Good Guy."
echo "Bad Guy."
寫一個腳本:
計算100以内所有奇數的和以及所有偶數的和;分别顯示之;
EvenSum=0
OddSum=0
for I in {1..100}; do
if [ $[$I%2] -eq 0 ]; then
EvenSum=$[$EvenSum+$I]
else
OddSum=$[$OddSum+$I]
echo "EvenSum is: $EvenSum. OddSum is: $OddSum."
bash程式設計: 位置變量
$1, $2, $3, $4, ...
計算N以内所有奇數的和以及所有偶數的和;分别顯示之;N是通過參數傳遞過來的正整數;
for I in `seq 1 $1`;do
if [ $[$I%2] -eq 1 ]; then
echo "EvenSum: $EvenSum."
echo "OddSUm: $OddSum."
echo "Sum: $[$EvenSum+$OddSum]"
shift [n]:實作位置參數輪替;
例子:通過參數傳遞n個正整數給腳本,求其和;
for I in `seq 1 $#`; do
Sum=$[$Sum+$1]
shift
echo $Sum
練習,寫一個腳本,完成以下要求:
1、添加10個使用者user1, user2, ..., user10;但要先判斷使用者是否存在,不存在而後再添加;
2、添加完成後,顯示一共添加了幾個使用者;當然,不能包括因為事先存在而沒有添加的;
3、最後顯示目前系統上共有多少個使用者;
Count=0
for I in {1..10}; do
if id user$I &> /dev/null; then
echo "user$I exists."
useradd user$I
echo "Add user$I successfully."
Count=$[$Count+1]
echo "Add $Count new users."
echo "Total users: `wc -l /etc/passwd | cut -d' ' -f1`."
1、通過參數傳遞一系列使用者名給腳本,讓腳本添加這些使用者;但要先判斷使用者是否存在,不存在而後再添加;
for UserName in $@; do
if id $UserName &> /dev/null; then
echo "$UserName exists."
useradd $UserName
echo "Add $UserName successfully."
給定一個使用者:
1、如果其UID為0,就顯示此為管理者;
2、否則,就顯示其為普通使用者;
練習:寫一個腳本,完成以下要求:
通過參數傳遞一個磁盤裝置檔案給腳本,讓腳本來判斷其是否有擴充分區;有則顯示有,否則顯示為無;
練習:寫一個腳本
給定一個檔案,比如/etc/inittab
判斷這個檔案中是否有空白行;
如果有,則顯示其空白行數;否則,顯示沒有空白行。
練習:寫一個腳本;(要求:不使用id指令獲得其id号;)
給定一個使用者,判斷其UID與GID是否一樣
如果一樣,就顯示此使用者為“good guy”;否則,就顯示此使用者為“bad guy”。
給腳本傳遞兩個參數(整數);
顯示此兩者之和,之乘積;
寫一個腳本,分别顯示目前系統上所有預設shell為bash的使用者和預設shell為/sbin/nologin的使用者,并統計各類shell下的使用者總數。顯示結果形如:
BASH,3users,they are:
root,redhat,gentoo
NOLOGIN, 2users, they are:
bin,ftp
bash腳本知識點:
條件測試方式:
bash指令;
條件測試:
大于:-gt
大等:-ge
小等:-le
不等:-ne
指令執行狀态傳回值: 0-255
0: 正确執行
1-255: 錯誤執行
exit [n]
腳本執行的最後一條件指令的狀态傳回值;
bash字元測試:
>: 大于
<: 小于
==: 等于
=~: 判斷左邊的字元串是否能夠被右邊的模式所比對;通常用于[[]];
[[ $opt1 =~ $opt2 ]]
一般做行首、行尾錨定;不要加引号;
單目:
-z $STRING: 為空則為真,不空則為假;
-n $STRING: 為空則為假,不空則真;
例子:寫一個腳本,判定使用者的shell是否為bash;
[ "$Shell" == "/bin/bash" ]
Shell=`grep "^$1:" /etc/passwd | cut -d: -f7`
if [ "$Shell" == "/bin/bash" ]; then
echo "Bash User."
Ret=0
echo "Not Bash User."
Ret=9
exit $Ret
改進版:
if [ -z $Shell ]; then
echo "No such user or User's shell is null."
exit 10
例子:根據使用者shell的結束符是否為sh來判定其是否為登入使用者:
echo "No shell."
exit 3
if [[ "$Shell" =~ sh$ ]]; then
echo "Login User."
echo "None Login User."
Ret=4
判斷目前主機的CPU生産商,其資訊在/proc/cpuinfo檔案中vendor id一行中。
如果其生産商為GenuineIntel,就顯示其為Intel公司;
否則,就顯示其為AMD公司;
Vendor=`grep "vendor_id" /proc/cpuinfo | uniq | cut -d: -f2`
if [[ "$Vendor" =~ [[:space:]]*GenuineIntel$ ]]; then
echo "Intel"
echo "AMD"
通過參數傳遞一個字元串給腳本,如果傳遞的字元串為“memory”或“Memory”,就以MB為機關顯示目前主機的記憶體資訊;
否則,就顯示/proc/uptime檔案的内容。
if [[ $1 =~ [Mm]emory$ ]]; then
free -m
cat /proc/uptime
bash知識點:組合條件測試
-a: 與
-o: 或
!: 非,單目操作符
A=3
UID>=1, UID<=499
bash測試:
bash指令
[]
[[]]
test
bash指令組合測試:
&&: 與
||: 或
!: 非
寫一腳本,給定使用者,如果其不存在,就退出腳本。
if ! id $1 &> /dev/null; then
echo "No such user."
exit 6
if [ `id -u $1` -eq `id -g $1` ]; then
echo "Good Guy"
else
echo "Bad Guy"
[ $1 == "memory" -o $1 == "Memory" ]
bash條件判斷之多分支if語句:
文法格式:
if 條件1; then
elif 條件2; then
elif 條件3; then
如果其生産商為AuthenticAMD,就顯示其為AMD公司;
否則,就顯示無法識别;
if [[ $Vendor =~ [[:space:]]*GenuineIntel$ ]]; then
echo "intel"
elif [[ $Vendor =~ [[:space:]]*AuthenticAMD$ ]]; then
echo "Unknown"
練習:通過參數傳遞給腳本一個字元串,如Fedora, Gentoo, Redhat,判斷Linux發行版所處理主流發行系列:
如果為fedora, centos, redhat,就顯示RedHat;
[ $1 == fedora -o $1 == centos -o $1 == redhat ]
如果為suse, opensuse,就顯示為SUSE;
如果為ubuntu, mint, debian,就顯示為Debian;
否則,顯示為其它或無法識别;
寫一個腳本,其可以接受三個參數,最後一個參數為檔案名,但參數可變化,形如:
script.sh -a MageEdu /magedu.com/scripts/test1.sh
script.sh -d 2013-07-19 /magedu.com/scripts/test1.sh
script.sh -D 'some infomation' /magedu.com/scripts/test1.sh
此腳本能夠建立/magedu.com/scripts/test1.sh檔案,并且,如果給出了-a MageEdu,則檔案前兩行為:
# Author: MageEdu
如果給出了-d 2013-07-19,則檔案前兩行為:
# Date: 2013-07-19
如果給出了-D "some infomation",則檔案前兩行為:
# Description: some infomation
其它任何參數,均提示錯誤并退出;
進一步:如果沒有退出,則使用vim打開此檔案,并使用光标預設處于最後一行;
再進一步:儲存退出後,如果檔案有文法錯誤提示使用者有錯誤;
更進一步:如果沒有文法錯誤,則給些檔案賦予執行權限;
a.sh -a mageedu /tmp/test.sh
# Author: mageedu
a.sh -d 2013-07-19 /tmp/test.sh
a.sh -D "test script" /tmp/test.sh
# Description: test script
mkscript
if [ $# -ne 3 ]; then
echo "the number of arguements is wrong."
exit 4
echo '#!/bin/bash' >> $3
if [ $1 == '-a' ]; then
echo "# Author: $2" >> $3
elif [ $1 == '-d' ]; then
echo "# Date: $2" >> $3
elif [ $1 == '-D' ]; then
echo "# Description: $2" >> $3
echo "Unknown option, ignore it."
rm -f $3
exit 5
vim + $3
if bash -n $3 &> /dev/null; then
chmod +x $3
echo "Syntax wrong in $3."
bash測試之檔案測試:
操作符 檔案路徑
-f: 測試其是否為普通檔案,即ls -l時檔案類型為-的檔案;
-d: 測試其是否為目錄檔案,即ls -l時檔案類型為d的檔案;
-e: 測試檔案是否存在;存在為真,否則為假;
-r: 測試檔案對目前使用者來說是否可讀;
-w: 測試檔案對目前使用者來說是否可寫;
-x: 測試檔案對目前使用者來說是否可執行;
-s: 測試檔案大小是否不空,不空則真,空則假;
如果/tmp/test10不存在,就建立之;
if [ ! -e /tmp/test10 ]; then
mkdir /tmp/test10
短路操作:隻要前半段已經可以決定最終結果,後半段就不再運算;
與運算:
真 && 真 = 真
真 && 假 = 假
假 && {真|假} = 假
或運算:
假 || 0 = 0
假 || 1 = 1
真 || =1
[ -e /tmp/test10 ] || mkdir /tmp/test10
id $UserName &> /dev/null || useradd $UserName
! id $UserName &> /dev/null && useradd $UserName || echo "$UserName exists."
id $UserName &> /dev/null && echo "$UserName exists." || useradd $UserName
例子:給定一個路徑,判斷
如果為普通檔案,顯示之;
如果為目錄,顯示之;
否則,說無法識别;
if [ ! -e $1 ]; then
echo "No such file."
exit 7
if [ -f $1 ]; then
echo "Common file."
elif [ -d $1 ]; then
echo "Directory."
echo "Unknown file."
bash的特殊參數:$0: 腳本名稱;
/tmp/script.sh
basename $0
寫一個腳本:可以接受一個參數,其使用形式如下:
script.sh {start|stop|restart|status}
如果參數為start,建立空檔案/var/lock/subsys/script,并顯示“Starting script successfully.”;
如果參數為stop,則删除檔案/var/lock/subsys/script,并顯示“Stop script finished.”;
如果參數為restart,則删除檔案/var/lock/subsys/script後重新建立,并顯示“Restarting script successfully.”;
如果參數為status,那麼:
如果/var/lock/subsys/script檔案存在,則顯示為“script is running.”
否則,則顯示為“script is stopped.”
其它任何參數:則顯示“script.sh {start|stop|restart|status}”
進一步:修改start的機制為:
如果參數為start,且/var/lock/subsys/script檔案不存在,則建立空檔案/var/lock/subsys/script,并顯示“Starting script successfully.”;
否則,顯示“script is already running.”
進一步:修改stop的機制為:
如果參數為stop,且/var/lock/subsys/script檔案存在,則删除檔案/var/lock/subsys/script,并顯示“Stop script finished.”;
否則,顯示“script is stopped yet.”
SysV網絡服務腳本:
# service network restart
# /etc/rc.d/init.d/network start
# /etc/init.d/network start
SvcName=`basename $0`
LockFile="/var/lock/subsys/$SvcName"
if [ $# -lt 1 ]; then
echo "Usage: $SvcName {start|stop|restart|status}"
if [ $1 == 'start' ]; then
if [ -e $LockFile ]; then
echo "$SvcName is running."
touch $LockFile &> /dev/null
echo "Starting $SvcName successfully."
elif [ $1 == 'stop' ]; then
if [ -e $LockFile ];then
rm -f $LockFile &> /dev/null
echo "Stopping $SvcName finished."
echo "$SvcName is stopped yet."
elif [ $1 == 'restart' ]; then
rm -f $LockFile &> /dev/null
touch $LockFile &> /dev/null
echo "Restarting $SvcName successfully."
elif [ $1 == 'status' ]; then
echo "$SvcName is stopped."
字元串測試:
>
<
==
!=
-z
-n
=~:模式比對檢測;
檔案測試:
-e
-f
-d
-r
-w
-x
-s
測試條件的邏輯組合:組合測試
與:-a
或:-o
非:!
與:&&
或:||
if [ $# -gt 1 -a $# -lt 10 ]
if id $UserName &> /dev/null && [ `id -u $UserName` -ge 500 ]; then
給定一個檔案:
如果是一個普通檔案,就顯示之;
如果是一個目錄,亦顯示之;
否則,此為無法識别之檔案;
File=
if [ -f $File ]; then
echo
elif [ -d $File ]; then
echo
判斷某目錄中所有檔案的類型:
for File in /var/log/*; do
bash的程式設計之case語句:用法格式
case 變量引用(${}) in
value1)
;;
value2)
value3)
*)
esac
Com=$1
if [ -z $Com ]; then
Com=gzip
[ -d /backup ] || mkdir /backup
case $Com in
gzip)
tar zcf /backup/etc-`date +%F-%H-%M-%S`.tar.gz /etc/*
RetVal=$?
;;
bzip2)
tar jcf /backup/etc-`date +%F-%H-%M-%S`.tar.bz2 /etc/*
xz)
tar Jcf /backup/etc-`date +%F-%H-%M-%S`.tar.xz /etc/*
echo "Usage: `basename $0` {[gzip|bzip2|xz]}"
esac
[ $RetVal -eq 0 ] && echo "Backup etc finished.($Com)."
case語句解決上一個服務腳本的問題:
LockFile=/var/lock/subsys/$SvcName
echo "Usage: $SvcName {start|restart|stop|status}"
case $1 in
start)
touch $LockFile
echo "Starting $SvcName finished." ;;
stop)
rm -f $LockFile
echo "Stopping $SvcName finished." ;;
restart)
echo "Restarting $SvcName finished." ;;
status)
echo "$SvcName is running..."
echo "$SvcName is stopped..."
練習:判斷目前Linux發行版是RedHat, Fedora, CentOS還是其它。
方法:取得/etc/issue檔案第一行的第一個單詞後進行比較;
bash如何與使用者互動:bash内置指令, read
-p "prompt":提示資訊
-t #: 逾時秒數
例子:
read -p "Do you agree [yes|no]?: " YesNo
case $YesNo in
y|Y|[Yy]es)
echo "Agreed, proceed." ;;
n|N|[nN]o)
echo "Disagreed, can't proceed." ;;
echo "Invalid input." ;;
例子:寫一個腳本
1、顯示如下菜單給使用者:
m|M) show memory usages;
d|D) show disk usages;
q|Q) quit
2、如果使用者選擇了第一項,則顯示記憶體使用資訊;
如果選擇了第二項,則顯示磁盤挂載及使用相關資訊;
如果是第三項,退出,并顯示選擇退出;
其它任何内容,均說明錯誤選項;
cat << EOF
EOF
read -p "Your choice: " Choice
case $Choice in
m|M)
free -m ;;
d|D)
df -lh ;;
q|Q)
echo "Quit..."
exit 0
echo "Invalid input."
exit 5