linux bash脚本编程知识点
生活随笔
收集整理的這篇文章主要介紹了
linux bash脚本编程知识点
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
bash變量類型:
環(huán)境變量
本地變量(局部變量)
位置變量
特殊變量
本地變量:
set VARNAME=VALUE: 作用域?yàn)檎麄€bash進(jìn)程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域?yàn)楫?dāng)前代碼段;
環(huán)境變量:作用域?yàn)楫?dāng)前shell進(jìn)程及其子進(jìn)程;
export VARNAM
E=VALUE
VARNAME=VALUE
export VARNAME
“導(dǎo)出”
腳本在執(zhí)行時會啟動一個子shell進(jìn)程
命令行中啟動的腳本會繼承當(dāng)前shell環(huán)境變量
系統(tǒng)自動執(zhí)行的腳本(非命令行啟動)就需要自我定義需要各環(huán)境變量
位置變量:
$1, $2, ...
$?: 保存上一個命令的執(zhí)行狀態(tài)返回值;
程序執(zhí)行,可能有兩類返回值:
程序執(zhí)行結(jié)果
程序狀態(tài)返回代碼(0-255)
0: 正確執(zhí)行
1-255:錯誤執(zhí)行,1,2,127系統(tǒng)預(yù)留;
撤消變量:
unset VARNAME
查看當(dāng)shell中變量:
set
查看當(dāng)前shell中的環(huán)境變量:
printenv
env
export
腳本:命令的堆砌,按實(shí)際需要,結(jié)合命令流程控制機(jī)制實(shí)現(xiàn)的源程序
shebang: 魔數(shù)
#!/bin/bash
# 注釋行,不執(zhí)行
/dev/null: 軟件設(shè)備, bit bucket,數(shù)據(jù)黑洞
腳本在執(zhí)行時會啟動一個子shell進(jìn)程;
命令行中啟動的腳本會繼承當(dāng)前shell環(huán)境變量;
;
練習(xí):寫一個腳本,完成以下任務(wù)
1、添加5個用戶, user1,..., user5
2、每個用戶的密碼同用戶名,而且要求,添加密碼完成后不顯示passwd命令的執(zhí)行結(jié)果信息;
3、每個用戶添加完成后,都要顯示用戶某某已經(jīng)成功添加;
useradd user1
echo "user1" | passwd --stdin user1 &> /dev/null
echo "Add user1 successfully."
條件判斷:
如果用戶不存在
添加用戶,給密碼并顯示添加成功;
否則
顯示如果已經(jīng)沒在,沒有添加;
bash中如何實(shí)現(xiàn)條件判斷?
條件測試類型:
整數(shù)測試
字符測試
文件測試
條件測試的表達(dá)式:
[ expression ]
[[ expression ]]
test expression
整數(shù)比較:
-eq: 測試兩個整數(shù)是否相等;比如 $A -eq $B
-ne: 測試兩個整數(shù)是否不等;不等,為真;相等,為假;
-gt: 測試一個數(shù)是否大于另一個數(shù);大于,為真;否則,為假;
-lt: 測試一個數(shù)是否小于另一個數(shù);小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
命令的間邏輯關(guān)系:
邏輯與: &&
第一個條件為假時,第二條件不用再判斷,最終結(jié)果已經(jīng)有;
第一個條件為真時,第二條件必須得判斷;
邏輯或: ||
如果用戶user6不存在,就添加用戶user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab文件的行數(shù)大于100,就顯示好大的文件;
[ `wc -l /etc/inittab | cut -d' ' -f1` -gt 100 ] && echo "Large file."
變量名稱:
1、只能包含字母、數(shù)字和下劃線,并且不能數(shù)字開頭;
2、不應(yīng)該跟系統(tǒng)中已有的環(huán)境變量重名;
3、最好做到見名知義;
如果用戶存在,就顯示用戶已存在;否則,就添加此用戶;
id user1 && echo "user1 exists." || useradd user1
如果用戶不存在,就添加;否則,顯示其已經(jīng)存在;
! id user1 && useradd user1 || echo "user1 exists."
如果用戶不存在,添加并且給密碼;否則,顯示其已經(jīng)存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdin user1 || echo "user1 exists."
練習(xí),寫一個腳本,完成以下要求:
1、添加3個用戶user1, user2, user3;但要先判斷用戶是否存在,不存在而后再添加;
2、添加完成后,顯示一共添加了幾個用戶;當(dāng)然,不能包括因?yàn)槭孪却嬖诙鴽]有添加的;
3、最后顯示當(dāng)前系統(tǒng)上共有多少個用戶;
如果 UID為0;那么
? 顯示為管理員
否則
? 顯示為普通用戶
??
NAME=user16
USERID=`id -u $NAME`
if [ $USERID -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi//結(jié)束
NAME=user16
if [ `id -u $NAME` -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi
練習(xí):寫一個腳本
判斷當(dāng)前系統(tǒng)上是否有用戶的默認(rèn)shell為bash;
? ?如果有,就顯示有多少個這類用戶;否則,就顯示沒有這類用戶;
#!/bin/bash
#
grep "\<bash$" /etc/passwd &> /dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
grep "\<bash$" /etc/passwd | wc -l
else
echo "No such user."
fi
練習(xí):寫一個腳本
給定一個文件,比如/etc/inittab?
判斷這個文件中是否有空白行;
如果有,則顯示其空白行數(shù);否則,顯示沒有空白行。
#!/bin/bash
A=`grep '^$' /etc/inittab | wc -l`
if [ $A -gt 0 ]; then
?echo "$A"
else
?echo "meiyoukongbaihang"
fi
? ? ? ? ? ? ? ??
?
#!/bin/bash
FILE=/etc/inittab
if [ ! -e $FILE ]; then
? echo "No $FILE."
? exit 8
fi
if grep "^$" $FILE &> /dev/null; then
? echo "Total blank lines: `grep "^$" $FILE | wc -l`."?
else
? echo "No blank line."
fi
練習(xí):寫一個腳本
給定一個用戶,判斷其UID與GID是否一樣
如果一樣,就顯示此用戶為“good guy”;否則,就顯示此用戶為“bad guy”。
#!/bin/bash
USERNAME=user1
USERID=`id -u $USERNAME`
GROUPID=`id -g $USERNAME`
if [ $USERID -eq $GROUPID ]; then
? echo "Good guy."
else
? echo "Bad guy."
fi
進(jìn)一步要求:不使用id命令獲得其id號;
#!/bin/bash
#
USERNAME=user1
if ! grep "^$USERNAME\>" /etc/passwd &> /dev/null; then
? echo "No such user: $USERNAME."
? exit 1
fi
USERID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f3`
GROUPID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f4`
if [ $USERID -eq $GROUPID ]; then
? echo "Good guy."
else
? echo "Bad guy."
fi
練習(xí):寫一個腳本
給定一個用戶,獲取其密碼警告期限;
而后判斷用戶密碼使用期限是否已經(jīng)小于警告期限;
提示:計算方法,最長使用期限減去已經(jīng)使用的天數(shù)即為剩余使用期限;
如果小于,則顯示“Warning”;否則,就顯示“OK”。
圓整:丟棄小數(shù)點(diǎn)后的所有內(nèi)容
#!/bin/bash
W=`grep "student" /etc/shadow | cut -d: -f6`
S=`date +%s`
T=`expr $S/86400`
L=`grep "^student" /etc/shadow | cut -d: -f5`
N=`grep "^student" /etc/shadow | cut -d: -f3`
SY=$[$L-$[$T-$N]]
if [ $SY -lt $W ]; then
? echo 'Warning'
else
? echo 'OK'
fi
練習(xí):寫一個腳本
判定命令歷史中歷史命令的總條目是否大于1000;如果大于,則顯示“Some command will gone.”;否則顯示“OK”。
shell中如何進(jìn)行算術(shù)運(yùn)算:
A=3
B=6
1、let 算術(shù)運(yùn)算表達(dá)式
let C=$A+$B
2、$[算術(shù)運(yùn)算表達(dá)式]
C=$[$A+$B]
3、$((算術(shù)運(yùn)算表達(dá)式))
C=$(($A+$B))
4、expr 算術(shù)運(yùn)算表達(dá)式,表達(dá)式中各操作數(shù)及運(yùn)算符之間要有空格,而且要使用命令引用
C=`expr $A + $B`
條件判斷,控制結(jié)構(gòu):
單分支if語句
if 判斷條件; then
? statement1
? statement2
? ...
fi
雙分支的if語句:
if 判斷條件; then
statement1
statement2
...
else
statement3
statement4
...
fi
多分支的if語句:
if 判斷條件1; then
? statement1
? ...
elif 判斷條件2; then
? statement2
? ...
elif 判斷條件3; then
? statement3
? ...
else
? statement4
? ...
fi
測試方法:
[ expression ]
[[ expression ]]
test expression
bash中常用的條件測試有三種:
整數(shù)測試:
-eq: 測試兩個整數(shù)是否相等;比如 $A -eq $B
-ne: 測試兩個整數(shù)是否不等;不等,為真;相等,為假;
-gt: 測試一個數(shù)是否大于另一個數(shù);大于,為真;否則,為假;
-lt: 測試一個數(shù)是否小于另一個數(shù);小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
INT1=63
INT2=77
[ $INT1 -eq $INI2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2 ?
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當(dāng)前用戶對指定文件是否有讀取權(quán)限;
-w
-x
[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
練習(xí):寫一個腳本
給定一個文件:
如果是一個普通文件,就顯示之;
如果是一個目錄,亦顯示之;
否則,此為無法識別之文件;
定義腳本退出狀態(tài)碼
exit: 退出腳本
exit #
如果腳本沒有明確定義退出狀態(tài)碼,那么,最后執(zhí)行的一條命令的退出碼即為腳本的退出狀態(tài)碼;
測試腳本是否有語法錯誤:
bash -n 腳本
bash -x 腳本:單步執(zhí)行
bash變量的類型:
本地變量:
set VARNAME=VALUE: 作用域?yàn)檎麄€bash進(jìn)程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域?yàn)楫?dāng)前代碼段;
環(huán)境變量:作用域?yàn)楫?dāng)前shell進(jìn)程及其子進(jìn)程;
export VARNAME=VALUE
VARNAME=VALUE
export VARNAME
“導(dǎo)出”
腳本在執(zhí)行時會啟動一個子shell進(jìn)程
命令行中啟動的腳本會繼承當(dāng)前shell環(huán)境變量
系統(tǒng)自動執(zhí)行的腳本(非命令行啟動)就需要自我定義需要各環(huán)境變量
位置變量:?
$1, $2, ...
shift
特殊變量:
$?
$#:參數(shù)的個數(shù)
$*: 參數(shù)列表
$@:參數(shù)列表
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
練習(xí):寫一腳本
能接受一個參數(shù)(文件路徑)
判定:此參數(shù)如果是一個存在的文件,就顯示“OK.”;否則就顯示"No such file."
練習(xí):寫一個腳本
給腳本傳遞兩個參數(shù)(整數(shù));
顯示此兩者之和,之乘積;
#!/bin/bash
#
if [ $# -lt 2 ]; then
? echo "Usage: cacl.sh ARG1 ARG2"
? exit 8
fi
echo "The sum is: $[$1+$2]."
echo "The prod is: $[$1*$2]."
練習(xí):寫一個腳本,完成以下任務(wù)
1、使用一個變量保存一個用戶名;
2、刪除此變量中的用戶,且一并刪除其家目錄;
3、顯示“用戶刪除完成”類的信息
bash:?
引用變量:${VARNAME}, 括號有時可省略。
整型,8bit: 256
0-255, 溢出
變量:
1,10000
10:16bit
10: 1010, 8bit
編程能力:
腳本編程
#abc
# hello world
? ?# hi world
練習(xí):
傳遞一個用戶名參數(shù)給腳本,判斷此用戶的用戶名跟其基本組的組名是否一致,并將結(jié)果顯示出來。
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
練習(xí):寫一個腳本
傳遞一個參數(shù)(單字符就行)給腳本,如參數(shù)為q,就退出腳本;否則,就顯示用戶的參數(shù);
練習(xí):寫一個腳本
傳遞一個參數(shù)(單字符就行)給腳本,如參數(shù)為q、Q、quit或Quit,就退出腳本;否則,就顯示用戶的參數(shù);
#!/bin/bash
#
if [ $1 = 'q' ];then
? echo "Quiting..."
? exit 1
elif [ $1 = 'Q' ];then
? echo "Quiting..."
? exit 2 ?
elif [ $1 = 'quit' ];then
? echo "Quiting..."
? exit 3?
elif [ $1 = 'Quit' ];then
? echo "Quiting..."
? exit 4 ?
else
? echo $1
fi
練習(xí):
if [ $# -lt 2 ];
傳遞三個參數(shù)給腳本,第一個為整數(shù),第二個為算術(shù)運(yùn)算符,第三個為整數(shù),將計算結(jié)果顯示出來,要求保留兩位精度。形如:
./calc.sh 5 / 2
#!/bin/bash
#
A=$1
x=$2
B=$3
result= echo "scale=2;$A$x$B;"|bc
echo $result
etco "scale=2;111/22" | bc ? //結(jié)果為5.04
練習(xí):
傳遞3個參數(shù)給腳本,參數(shù)均為用戶名。將此些用戶的帳號信息提取出來后放置于/tmp/testusers.txt文件中,并要求每一行行首有行號。
egrep “$1|$2|$3” /etc/passwd >>/tmp/a
cat ?n /tmp/a > /tmp/test0
rm ?rf a
寫一個腳本:
判斷當(dāng)前主機(jī)的CPU生產(chǎn)商,其信息在/proc/cpuinfo文件中vendor id一行中。
如果其生產(chǎn)商為AuthenticAMD,就顯示其為AMD公司;
如果其生產(chǎn)商為GenuineIntel,就顯示其為Intel公司;
否則,就說其為非主流公司;
#!/bin/bash
VENDOR_ID=`grep vendor_id /proc/cpuinfo | head -1 | cut -d' ' -f2`?
if [ $VENDOR_ID == "AuthenticAMD" ]; then
? ? echo "AMD company"
elif [ $VENDOR_ID == "GenuineIntel" ]; then
? ? echo "Intel company"
fi
寫一個腳本:
給腳本傳遞三個整數(shù),判斷其中的最大數(shù)和最小數(shù),并顯示出來。
MAX=0
MAX -eq $1
MAX=$1
MAX -lt $2
MAX=$2
例:比較三個數(shù)的大小
echo -n "Enter three number:"
read a b c
if [ $a -gt $b ];then
?t=$a;a=$b;b=$t;
fi
if [ $a -gt $c ];then
?t=$a;a=$c;c=$t;
fi
if [ $b -gt $c ];then
?t=$b;b=$c;c=$t;
fi
echo "From small to big:$a,$b,$c"
例:求1到100的和
#!/bin/bash
declare ?-i SUM=0
for I in {1..100};do
? ? ? SUM=$[$SUM+$I]
done
echo “The SUM is :$SUM。”
循環(huán):進(jìn)入條件,退出條件
for
while
until
for 變量 in 列表; do
? 循環(huán)體
done
for I in 1 2 3 4 5 6 7 8 9 10; do
? 加法運(yùn)算
done
遍歷完成之后,退出;
如何生成列表:
{1..100}
`seq [起始數(shù) [步進(jìn)長度]] 結(jié)束數(shù)`
1,...,100
declare -i SUM=0
integer
-x//環(huán)境變量
寫一個腳本:
1、設(shè)定變量FILE的值為/etc/passwd
2、依次向/etc/passwd中的每個用戶問好,并顯示對方的shell,形如: ?
Hello, root, your shell: /bin/bash
#!/bin/bash
for I in `cat /etc/passwd |grep 'bash'`;do
? ? ? ?echo"hello `echo $I |cut -d: -f1` your bash"
done
3、統(tǒng)計一共有多少個用戶
for I in `seq 1 $LINES`; do echo "Hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`"; done
只向默認(rèn)shell為bash的用戶問聲好
寫一個腳本:
1、添加10個用戶user1到user10,密碼同用戶名;但要求只有用戶不存在的情況下才能添加;
#!/bin/bash
if [ $1 == add];then
for I in{1..10};do
? ? ? ?! id user$I &&useradd user$I -puser$I
done
elif [ $1 == del];then
? ? ? ?for I in {1..10};do
? ? ? ? ? ? ? id user$I >/dev/null &&userdel user$I
? ? ? ?done
else
? ? ? ?echo "paramiter wrong"
fi
擴(kuò)展:
接受一個參數(shù):
add: 添加用戶user1..user10
del: 刪除用戶user1..user10
其它:退出
adminusers user1,user2,user3,hello,hi
寫一個腳本:
計算100以內(nèi)所有能被3整除的正整數(shù)的和;
取模,取余:%
3%2=1
100%55=45
寫一個腳本:
let I=$[$I+1]
SUM=$[$SUM+$I]
-=
let I-=1 相當(dāng)于 let I--
++I, --I
*=
/=
%=
測試:
整數(shù)測試:
-eq: 測試兩個整數(shù)是否相等;比如 $A -eq $B
-ne: 測試兩個整數(shù)是否不等;不等,為真;相等,為假;
-gt: 測試一個數(shù)是否大于另一個數(shù);大于,為真;否則,為假;
-lt: 測試一個數(shù)是否小于另一個數(shù);小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當(dāng)前用戶對指定文件是否有讀取權(quán)限;
-w
-x
if [ $# -gt 1 ]; then
組合測試條件
-a: 與關(guān)系
-o: 或關(guān)系
!: 非關(guān)系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
生成隨機(jī)數(shù)?
RANDOM: 0-32768
隨機(jī)數(shù)生成器:熵池
/dev/random:
/dev/urandom:
寫一個腳本,利用RANDOM生成10個隨機(jī)數(shù),并找 出其中的最大值,和最小值;
#!/bin/bash
#
declare -i MAX=0
declare -i MIN=0
for I in {1..10}; do
? MYRAND=$RANDOM
? [ $I -eq 1 ] && MIN=$MYRAND
? if [ $I -le 9 ]; then
? ? echo -n "$MYRAND,"
? else
? ? echo "$MYRAND"
? fi
? [ $MYRAND -gt $MAX ] && MAX=$MYRAND
? [ $MYRAND -lt $MIN ] && MIN=$MYRAND
done
echo $MAX, $MIN
面向過程
控制結(jié)構(gòu)
順序結(jié)構(gòu)
選擇結(jié)構(gòu)
循環(huán)結(jié)構(gòu)
選擇結(jié)構(gòu):
if: 單分支、雙分支、多分支
if CONDITION; then
? statement
? ...
fi
if CONDITION; then
? statement
? ...
else
? statement
? ...
fi
if CONDITION1; then
? statement
? ...
elif CONDITION2; then
? statement
? ...
esle
? statement
? ...
fi
case語句:選擇結(jié)構(gòu)
case SWITCH in?
value1)
? statement
? ...
? ;;
value2)
? statement
? ...
? ;;
*)
? statement
? ...
? ;;
esac
a-z
A-Z
0-9
[abc]
只接受參數(shù)start,stop,restart,status其中之一
#!/bin/bash
#
DEBUG=0
ADD=0
DEL=0
for I in `seq 0 $#`; do
? if [ $# -gt 0 ]; then
?case $1 in
?-v|--verbose)
DEBUG=1
shift ;;
?-h|--help)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 0
;;
?--add)
ADD=1
ADDUSERS=$2
shift 2
;;
?--del)
DEL=1
DELUSERS=$2
shift 2
;;
?*)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 7
;;
? ? esac
? fi
done
if [ $ADD -eq 1 ]; then
? for USER in `echo $ADDUSERS | sed 's@,@ @g'`; do
? ? if id $USER &> /dev/null; then
? ? ? [ $DEBUG -eq 1 ] && echo "$USER exists."
? ? else
? ? ? useradd $USER
? ? ? [ $DEBUG -eq 1 ] && echo "Add user $USER finished."
? ? fi
? done
fi
if [ $DEL -eq 1 ]; then
? for USER in `echo $DELUSERS | sed 's@,@ @g'`; do
? ? if id $USER &> /dev/null; then
? ? ? userdel -r $USER
? ? ? [ $DEBUG -eq 1 ] && echo "Delete $USER finished."
? ? else
? ? ? [ $DEBUG -eq 1 ] && echo "$USER not exist."
? ? fi
? done
fi
練習(xí):寫一個腳本showlogged.sh,其用法格式為:
showlogged.sh -v -c -h|--help
其中,-h選項(xiàng)只能單獨(dú)使用,用于顯示幫助信息;-c選項(xiàng)時,顯示當(dāng)前系統(tǒng)上登錄的所有用戶數(shù);如果同時使用了-v選項(xiàng),則既顯示同時登錄的用戶數(shù),又顯示登錄的用戶的相關(guān)信息;如
Logged users: 4.?
They are:
root ? ? tty2 ? ? ? ? Feb 18 02:41
root ? ? pts/1 ? ? ? ?Mar ?8 08:36 (172.16.100.177)
root ? ? pts/5 ? ? ? ?Mar ?8 07:56 (172.16.100.177)
hadoop ? pts/6 ? ? ? ?Mar ?8 09:16 (172.16.100.177)
#!/bin/bash
#
declare -i SHOWNUM=0
declare -i SHOWUSERS=0
for I in `seq 1 $#`; do
? if [ $# -gt 0 ]; then
? ? case $1 in
? ? -h|--help)
? ? ? echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
? ? ? exit 0 ;;
? ? -v|--verbose)
? ? ? let SHOWUSERS=1
? ? ? shift ;;
? ? -c|--count)
? ? ? let SHOWNUM=1
? ? ? shift ;;
? ? *)
? ? ? echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
? ? ? exit 8 ;;
? ? esac
? fi
done
if [ $SHOWNUM -eq 1 ]; then
? echo "Logged users: `who | wc -l`."
? if [ $SHOWUSERS -eq 1 ]; then
? ? echo "They are:"
? ? who
? fi
fi
腳本編程:
順序結(jié)構(gòu)
選擇結(jié)構(gòu)
if
case
循環(huán)結(jié)構(gòu)
for
while
until
while循環(huán):適用于循環(huán)次數(shù)未知的場景,要有退出條件
語法:
while CONDITION; do
?statement
?...
done
計算100以內(nèi)所有正整數(shù)的和
#!/bin/bash
declare -i I=1
declare -i SUM=0
while [ $I -le 100 ]; do
? let SUM+=$I
? let I++
done
echo $SUM
練習(xí):轉(zhuǎn)換用戶輸入的字符為大寫,除了quit:
#!/bin/bash
#
read -p "Input something: " STRING
while [ $STRING != 'quit' ]; do
? echo $STRING | tr 'a-z' 'A-Z'
? read -p "Input something: " STRING
done
練習(xí):每隔5秒查看hadoop用戶是否登錄,如果登錄,顯示其登錄并退出;否則,顯示當(dāng)前時間,并說明hadoop尚未登錄:
#!/bin/bash
#
who | grep "hadoop" &> /dev/null
RETVAL=$?
while [ $RETVAL -ne 0 ]; do
? echo "`date`, hadoop is not log."?
? sleep 5
? who | grep "hadoop" &> /dev/null
? RETVAL=$?
done
echo "hadoop is logged in."
寫一個腳本:
1) 顯示一個菜單給用戶:?
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
2) 當(dāng)用戶給定選項(xiàng)后顯示相應(yīng)的內(nèi)容;
? ?
擴(kuò)展:
當(dāng)用戶選擇完成,顯示相應(yīng)信息后,不退出;而讓用戶再一次選擇,再次顯示相應(yīng)內(nèi)容;除了用戶使用quit;
#!/bin/bash
#
cat << EOF
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
EOF
read -p "Your choice: " CHOICE
while [ $CHOICE != 'quit' ];do
? case $CHOICE in
? d|D)
? ? echo "Disk usage: "
? ? df -Ph ;;
? m|M)
? ? echo "Memory usage: "
? ? free -m | grep "Mem" ;;
? s|S)
? ? echo "Swap usage: "
? ? free -m | grep "Swap" ;;
? *)
? ? echo "Unknown.." ;;
? esac
read -p "Again, your choice: " CHOICE
done
腳本編程控制結(jié)構(gòu):
順序
選擇
if
case
循環(huán)
for?
while
until
while CONDITION; do
? statment
done
進(jìn)入循環(huán):條件滿足
退出循環(huán):條件不滿足
until CONDITION; do
? statement
? ...
done
進(jìn)入循環(huán):條件不滿足
退出循環(huán):條件滿足
for 變量 in 列表; do?
循環(huán)體
done
for (( expr1 ; expr2 ; expr3 )); do?
? 循環(huán)體
done
寫一個腳本:
1、通過ping命令測試192.168.0.151到192.168.0.254之間的所有主機(jī)是否在線,
如果在線,就顯示"ip is up.",其中的IP要換為真正的IP地址,且以綠色顯示;
如果不在線,就顯示"ip is down.",其中的IP要換為真正的IP地址,且以紅色顯示;
要求:分別使用while,until和for(兩種形式)循環(huán)實(shí)現(xiàn)。
寫一個腳本,完成以下功能:
1、提示用戶輸入一個用戶名;
2、顯示一個菜單給用戶,形如:
cat <<EOF
U|u ?show UID
G|g ?show GID
S|s ?show SHELL
Q|q ?quit
EOF
?#!bin/bash
? ? ? 2 #
? ? ? 3 cat << EOF
? ? ? 4 U|u ?show UID
? ? ? 5 G|g ?show GID
? ? ? 6 S|s ?show SHELL
? ? ? 7 Q|q ?quit
? ? ? 8 EOF
? ? ? 9 read -p "You choice: " CHOICE
? ? ?10 until [ $CHOICE == 'q' -o $CHOICE == 'Q' ]
? ? ?11 do
? ? ?12 case $CHOICE in
? ? ?13 d|D) df -lh;;
? ? ?14 m|M) free -m | grep "^Mem";;
? ? ?15 s|S) free -m | grep "^Swap";;
? ? ?16 *) read -p "You choice,again: " CHOICE;;
? ? ?17 esac
? ? ?18 read -p "You choice: " CHOICE
? ? ?19 done
函數(shù):功能, function
代碼重用:
庫:so
腳本編程之函數(shù):
function: 功能
結(jié)構(gòu)化編程,不能獨(dú)立運(yùn)行,需要調(diào)用時執(zhí)行,可以被多次調(diào)用
定義一個函數(shù):
function FUNCNAME {
? command
}
FUNCNAME() {
? command
}
自定義執(zhí)行狀態(tài)返回值:
return #
0-255
接受參數(shù)的函數(shù):
./a.sh m n?
$1: m
$2: n
sum()
{
echo $1+$2
TWOINT 5 6
$1: 5
$2: 6
練習(xí):寫一個腳本,判定192.168.0.200-192.168.0.254之間的主機(jī)哪些在線。要求:
1、使用函數(shù)來實(shí)現(xiàn)一臺主機(jī)的判定過程;
2、在主程序中來調(diào)用此函數(shù)判定指定范圍內(nèi)的所有主機(jī)的在線情況。
#!/bin/bash
#
PING() {
? for I in {200..254};do
? ? if ping -c 1 -W 1 192.168.0.$I &> /dev/null; then
? ? ? echo "192.168.0.$I is up."
? ? else
? ? ? echo "192.168.0.$I is down."
? ? fi
? done
}
PING
#!/bin/bash
#
PING() {
? ? if ping -c 1 -W 1 $1 &> /dev/null; then
? ? ? echo "$1 is up."
? ? else
? ? ? echo "$1 is down."
? ? fi
}
for I in {200..254}; do
? PING 192.168.0.$I
done
#!/bin/bash
#
PING() {
? ? if ping -c 1 -W 1 $1 &> /dev/null; then
? ? ? return 0
? ? else
? ? ? return 1
? ? fi
}
for I in {200..254}; do
? PING 192.168.0.$I
? if [ $? -eq 0 ]; then
? ? echo "192.168.0.$I is up."
? else
? ? echo "192.168.0.$I is down."
? fi
done
寫一個腳本:使用函數(shù)完成
1、函數(shù)能夠接受一個參數(shù),參數(shù)為用戶名;
? ?判斷一個用戶是否存在
? ?如果存在,就返回此用戶的shell和UID;并返回正常狀態(tài)值;
? ?如果不存在,就說此用戶不存在;并返回錯誤狀態(tài)值;
2、在主程序中調(diào)用函數(shù);
擴(kuò)展1:在主程序中,讓用戶自己輸入用戶名后,傳遞給函數(shù)來進(jìn)行判斷;
擴(kuò)展2:在主程序中,輸入用戶名判斷后不退出腳本,而是提示用戶繼續(xù)輸入下一個用戶名;如果用戶輸入的用戶不存在,請用戶重新輸入;但如果用戶輸入的是q或Q就退出;
#!/bin/bash
#
user () {
if id $1 &> /dev/null ;then
echo "`grep ^$1 ?/etc/passwd | cut -d: -f3,7`"
? ?return 0
else
? ?echo "no $1"
? ? return 1
fi
}
read -p "please input username:" username
until [ $username == q -o $username == Q ]; do
user $username
if [ $? == 0 ];then
read -p "please input again:" username
else
read -p "no $username,please input again:" username
fi
done
函數(shù)也可以接受參數(shù), 即可以向函數(shù)傳遞參數(shù)
函數(shù)接受一個用戶名參數(shù),顯示此用戶的shell和UID;
寫一個函數(shù):接受一命令參數(shù)ls
/bin/ls, /mnt/sysroot/bin/ls
/sbin/ifconfig, /mnt/sysroot/sbin/ifconfig
腳本編程知識點(diǎn):
1、變量中字符的長度:${#VARNAME}
2、變量賦值等:
${parameter:-word}:如果parameter為空或未定義,則變量展開為“word”;否則,展開為parameter的值;
${parameter:+word}:如果parameter為空或未定義,不做任何操作;否則,則展開為“word”值;
${parameter:=word}:如果parameter為空或未定義,則變量展開為“word”,并將展開后的值賦值給parameter;
${parameter:offset}
${parameter:offset:length}:取子串,從offset處的后一個字符開始,取lenth長的子串;
3、腳本配置文件
/etc/rc.d/init.d/服務(wù)腳本
服務(wù)腳本支持配置文件:/etc/sysconfig/服務(wù)腳本同名的配置文件
.conf為配置文件。
#!/bin/bash
#
./root/a.conf ?//把a(bǔ).conf這個文件加載進(jìn)來
local VAR_NAME=//必須用local
a=1
test() {
? a=$[3+4]
}
test
for I in `seq $a 10`; do
? echo $I
done ?
5、命令mktemp
創(chuàng)建臨時文件或目錄
mktemp /tmp/file.XX
-d: 創(chuàng)建為臨時目錄
6、信號
kill -SIG(NAL) PID
1: HUP
2: INT//終止
9: KILL
15: TERM
腳本中,能實(shí)現(xiàn)信號捕捉,但9和15無法捕捉
Ctrl+c: SIGINT
trap命令:
trap 'COMMAND' 信號列表?
7、一行執(zhí)行多個語句,語句間用分號分隔
環(huán)境變量
本地變量(局部變量)
位置變量
特殊變量
本地變量:
set VARNAME=VALUE: 作用域?yàn)檎麄€bash進(jìn)程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域?yàn)楫?dāng)前代碼段;
環(huán)境變量:作用域?yàn)楫?dāng)前shell進(jìn)程及其子進(jìn)程;
export VARNAM
E=VALUE
VARNAME=VALUE
export VARNAME
“導(dǎo)出”
腳本在執(zhí)行時會啟動一個子shell進(jìn)程
命令行中啟動的腳本會繼承當(dāng)前shell環(huán)境變量
系統(tǒng)自動執(zhí)行的腳本(非命令行啟動)就需要自我定義需要各環(huán)境變量
位置變量:
$1, $2, ...
$?: 保存上一個命令的執(zhí)行狀態(tài)返回值;
程序執(zhí)行,可能有兩類返回值:
程序執(zhí)行結(jié)果
程序狀態(tài)返回代碼(0-255)
0: 正確執(zhí)行
1-255:錯誤執(zhí)行,1,2,127系統(tǒng)預(yù)留;
撤消變量:
unset VARNAME
查看當(dāng)shell中變量:
set
查看當(dāng)前shell中的環(huán)境變量:
printenv
env
export
腳本:命令的堆砌,按實(shí)際需要,結(jié)合命令流程控制機(jī)制實(shí)現(xiàn)的源程序
shebang: 魔數(shù)
#!/bin/bash
# 注釋行,不執(zhí)行
/dev/null: 軟件設(shè)備, bit bucket,數(shù)據(jù)黑洞
腳本在執(zhí)行時會啟動一個子shell進(jìn)程;
命令行中啟動的腳本會繼承當(dāng)前shell環(huán)境變量;
;
練習(xí):寫一個腳本,完成以下任務(wù)
1、添加5個用戶, user1,..., user5
2、每個用戶的密碼同用戶名,而且要求,添加密碼完成后不顯示passwd命令的執(zhí)行結(jié)果信息;
3、每個用戶添加完成后,都要顯示用戶某某已經(jīng)成功添加;
useradd user1
echo "user1" | passwd --stdin user1 &> /dev/null
echo "Add user1 successfully."
條件判斷:
如果用戶不存在
添加用戶,給密碼并顯示添加成功;
否則
顯示如果已經(jīng)沒在,沒有添加;
bash中如何實(shí)現(xiàn)條件判斷?
條件測試類型:
整數(shù)測試
字符測試
文件測試
條件測試的表達(dá)式:
[ expression ]
[[ expression ]]
test expression
整數(shù)比較:
-eq: 測試兩個整數(shù)是否相等;比如 $A -eq $B
-ne: 測試兩個整數(shù)是否不等;不等,為真;相等,為假;
-gt: 測試一個數(shù)是否大于另一個數(shù);大于,為真;否則,為假;
-lt: 測試一個數(shù)是否小于另一個數(shù);小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
命令的間邏輯關(guān)系:
邏輯與: &&
第一個條件為假時,第二條件不用再判斷,最終結(jié)果已經(jīng)有;
第一個條件為真時,第二條件必須得判斷;
邏輯或: ||
如果用戶user6不存在,就添加用戶user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab文件的行數(shù)大于100,就顯示好大的文件;
[ `wc -l /etc/inittab | cut -d' ' -f1` -gt 100 ] && echo "Large file."
變量名稱:
1、只能包含字母、數(shù)字和下劃線,并且不能數(shù)字開頭;
2、不應(yīng)該跟系統(tǒng)中已有的環(huán)境變量重名;
3、最好做到見名知義;
如果用戶存在,就顯示用戶已存在;否則,就添加此用戶;
id user1 && echo "user1 exists." || useradd user1
如果用戶不存在,就添加;否則,顯示其已經(jīng)存在;
! id user1 && useradd user1 || echo "user1 exists."
如果用戶不存在,添加并且給密碼;否則,顯示其已經(jīng)存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdin user1 || echo "user1 exists."
練習(xí),寫一個腳本,完成以下要求:
1、添加3個用戶user1, user2, user3;但要先判斷用戶是否存在,不存在而后再添加;
2、添加完成后,顯示一共添加了幾個用戶;當(dāng)然,不能包括因?yàn)槭孪却嬖诙鴽]有添加的;
3、最后顯示當(dāng)前系統(tǒng)上共有多少個用戶;
如果 UID為0;那么
? 顯示為管理員
否則
? 顯示為普通用戶
??
NAME=user16
USERID=`id -u $NAME`
if [ $USERID -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi//結(jié)束
NAME=user16
if [ `id -u $NAME` -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi
練習(xí):寫一個腳本
判斷當(dāng)前系統(tǒng)上是否有用戶的默認(rèn)shell為bash;
? ?如果有,就顯示有多少個這類用戶;否則,就顯示沒有這類用戶;
#!/bin/bash
#
grep "\<bash$" /etc/passwd &> /dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
grep "\<bash$" /etc/passwd | wc -l
else
echo "No such user."
fi
練習(xí):寫一個腳本
給定一個文件,比如/etc/inittab?
判斷這個文件中是否有空白行;
如果有,則顯示其空白行數(shù);否則,顯示沒有空白行。
#!/bin/bash
A=`grep '^$' /etc/inittab | wc -l`
if [ $A -gt 0 ]; then
?echo "$A"
else
?echo "meiyoukongbaihang"
fi
? ? ? ? ? ? ? ??
?
#!/bin/bash
FILE=/etc/inittab
if [ ! -e $FILE ]; then
? echo "No $FILE."
? exit 8
fi
if grep "^$" $FILE &> /dev/null; then
? echo "Total blank lines: `grep "^$" $FILE | wc -l`."?
else
? echo "No blank line."
fi
練習(xí):寫一個腳本
給定一個用戶,判斷其UID與GID是否一樣
如果一樣,就顯示此用戶為“good guy”;否則,就顯示此用戶為“bad guy”。
#!/bin/bash
USERNAME=user1
USERID=`id -u $USERNAME`
GROUPID=`id -g $USERNAME`
if [ $USERID -eq $GROUPID ]; then
? echo "Good guy."
else
? echo "Bad guy."
fi
進(jìn)一步要求:不使用id命令獲得其id號;
#!/bin/bash
#
USERNAME=user1
if ! grep "^$USERNAME\>" /etc/passwd &> /dev/null; then
? echo "No such user: $USERNAME."
? exit 1
fi
USERID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f3`
GROUPID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f4`
if [ $USERID -eq $GROUPID ]; then
? echo "Good guy."
else
? echo "Bad guy."
fi
練習(xí):寫一個腳本
給定一個用戶,獲取其密碼警告期限;
而后判斷用戶密碼使用期限是否已經(jīng)小于警告期限;
提示:計算方法,最長使用期限減去已經(jīng)使用的天數(shù)即為剩余使用期限;
如果小于,則顯示“Warning”;否則,就顯示“OK”。
圓整:丟棄小數(shù)點(diǎn)后的所有內(nèi)容
#!/bin/bash
W=`grep "student" /etc/shadow | cut -d: -f6`
S=`date +%s`
T=`expr $S/86400`
L=`grep "^student" /etc/shadow | cut -d: -f5`
N=`grep "^student" /etc/shadow | cut -d: -f3`
SY=$[$L-$[$T-$N]]
if [ $SY -lt $W ]; then
? echo 'Warning'
else
? echo 'OK'
fi
練習(xí):寫一個腳本
判定命令歷史中歷史命令的總條目是否大于1000;如果大于,則顯示“Some command will gone.”;否則顯示“OK”。
shell中如何進(jìn)行算術(shù)運(yùn)算:
A=3
B=6
1、let 算術(shù)運(yùn)算表達(dá)式
let C=$A+$B
2、$[算術(shù)運(yùn)算表達(dá)式]
C=$[$A+$B]
3、$((算術(shù)運(yùn)算表達(dá)式))
C=$(($A+$B))
4、expr 算術(shù)運(yùn)算表達(dá)式,表達(dá)式中各操作數(shù)及運(yùn)算符之間要有空格,而且要使用命令引用
C=`expr $A + $B`
條件判斷,控制結(jié)構(gòu):
單分支if語句
if 判斷條件; then
? statement1
? statement2
? ...
fi
雙分支的if語句:
if 判斷條件; then
statement1
statement2
...
else
statement3
statement4
...
fi
多分支的if語句:
if 判斷條件1; then
? statement1
? ...
elif 判斷條件2; then
? statement2
? ...
elif 判斷條件3; then
? statement3
? ...
else
? statement4
? ...
fi
測試方法:
[ expression ]
[[ expression ]]
test expression
bash中常用的條件測試有三種:
整數(shù)測試:
-eq: 測試兩個整數(shù)是否相等;比如 $A -eq $B
-ne: 測試兩個整數(shù)是否不等;不等,為真;相等,為假;
-gt: 測試一個數(shù)是否大于另一個數(shù);大于,為真;否則,為假;
-lt: 測試一個數(shù)是否小于另一個數(shù);小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
INT1=63
INT2=77
[ $INT1 -eq $INI2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2 ?
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當(dāng)前用戶對指定文件是否有讀取權(quán)限;
-w
-x
[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
練習(xí):寫一個腳本
給定一個文件:
如果是一個普通文件,就顯示之;
如果是一個目錄,亦顯示之;
否則,此為無法識別之文件;
定義腳本退出狀態(tài)碼
exit: 退出腳本
exit #
如果腳本沒有明確定義退出狀態(tài)碼,那么,最后執(zhí)行的一條命令的退出碼即為腳本的退出狀態(tài)碼;
測試腳本是否有語法錯誤:
bash -n 腳本
bash -x 腳本:單步執(zhí)行
bash變量的類型:
本地變量:
set VARNAME=VALUE: 作用域?yàn)檎麄€bash進(jìn)程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域?yàn)楫?dāng)前代碼段;
環(huán)境變量:作用域?yàn)楫?dāng)前shell進(jìn)程及其子進(jìn)程;
export VARNAME=VALUE
VARNAME=VALUE
export VARNAME
“導(dǎo)出”
腳本在執(zhí)行時會啟動一個子shell進(jìn)程
命令行中啟動的腳本會繼承當(dāng)前shell環(huán)境變量
系統(tǒng)自動執(zhí)行的腳本(非命令行啟動)就需要自我定義需要各環(huán)境變量
位置變量:?
$1, $2, ...
shift
特殊變量:
$?
$#:參數(shù)的個數(shù)
$*: 參數(shù)列表
$@:參數(shù)列表
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
練習(xí):寫一腳本
能接受一個參數(shù)(文件路徑)
判定:此參數(shù)如果是一個存在的文件,就顯示“OK.”;否則就顯示"No such file."
練習(xí):寫一個腳本
給腳本傳遞兩個參數(shù)(整數(shù));
顯示此兩者之和,之乘積;
#!/bin/bash
#
if [ $# -lt 2 ]; then
? echo "Usage: cacl.sh ARG1 ARG2"
? exit 8
fi
echo "The sum is: $[$1+$2]."
echo "The prod is: $[$1*$2]."
練習(xí):寫一個腳本,完成以下任務(wù)
1、使用一個變量保存一個用戶名;
2、刪除此變量中的用戶,且一并刪除其家目錄;
3、顯示“用戶刪除完成”類的信息
bash:?
引用變量:${VARNAME}, 括號有時可省略。
整型,8bit: 256
0-255, 溢出
變量:
1,10000
10:16bit
10: 1010, 8bit
編程能力:
腳本編程
#abc
# hello world
? ?# hi world
練習(xí):
傳遞一個用戶名參數(shù)給腳本,判斷此用戶的用戶名跟其基本組的組名是否一致,并將結(jié)果顯示出來。
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
練習(xí):寫一個腳本
傳遞一個參數(shù)(單字符就行)給腳本,如參數(shù)為q,就退出腳本;否則,就顯示用戶的參數(shù);
練習(xí):寫一個腳本
傳遞一個參數(shù)(單字符就行)給腳本,如參數(shù)為q、Q、quit或Quit,就退出腳本;否則,就顯示用戶的參數(shù);
#!/bin/bash
#
if [ $1 = 'q' ];then
? echo "Quiting..."
? exit 1
elif [ $1 = 'Q' ];then
? echo "Quiting..."
? exit 2 ?
elif [ $1 = 'quit' ];then
? echo "Quiting..."
? exit 3?
elif [ $1 = 'Quit' ];then
? echo "Quiting..."
? exit 4 ?
else
? echo $1
fi
練習(xí):
if [ $# -lt 2 ];
傳遞三個參數(shù)給腳本,第一個為整數(shù),第二個為算術(shù)運(yùn)算符,第三個為整數(shù),將計算結(jié)果顯示出來,要求保留兩位精度。形如:
./calc.sh 5 / 2
#!/bin/bash
#
A=$1
x=$2
B=$3
result= echo "scale=2;$A$x$B;"|bc
echo $result
etco "scale=2;111/22" | bc ? //結(jié)果為5.04
練習(xí):
傳遞3個參數(shù)給腳本,參數(shù)均為用戶名。將此些用戶的帳號信息提取出來后放置于/tmp/testusers.txt文件中,并要求每一行行首有行號。
egrep “$1|$2|$3” /etc/passwd >>/tmp/a
cat ?n /tmp/a > /tmp/test0
rm ?rf a
寫一個腳本:
判斷當(dāng)前主機(jī)的CPU生產(chǎn)商,其信息在/proc/cpuinfo文件中vendor id一行中。
如果其生產(chǎn)商為AuthenticAMD,就顯示其為AMD公司;
如果其生產(chǎn)商為GenuineIntel,就顯示其為Intel公司;
否則,就說其為非主流公司;
#!/bin/bash
VENDOR_ID=`grep vendor_id /proc/cpuinfo | head -1 | cut -d' ' -f2`?
if [ $VENDOR_ID == "AuthenticAMD" ]; then
? ? echo "AMD company"
elif [ $VENDOR_ID == "GenuineIntel" ]; then
? ? echo "Intel company"
fi
寫一個腳本:
給腳本傳遞三個整數(shù),判斷其中的最大數(shù)和最小數(shù),并顯示出來。
MAX=0
MAX -eq $1
MAX=$1
MAX -lt $2
MAX=$2
例:比較三個數(shù)的大小
echo -n "Enter three number:"
read a b c
if [ $a -gt $b ];then
?t=$a;a=$b;b=$t;
fi
if [ $a -gt $c ];then
?t=$a;a=$c;c=$t;
fi
if [ $b -gt $c ];then
?t=$b;b=$c;c=$t;
fi
echo "From small to big:$a,$b,$c"
例:求1到100的和
#!/bin/bash
declare ?-i SUM=0
for I in {1..100};do
? ? ? SUM=$[$SUM+$I]
done
echo “The SUM is :$SUM。”
循環(huán):進(jìn)入條件,退出條件
for
while
until
for 變量 in 列表; do
? 循環(huán)體
done
for I in 1 2 3 4 5 6 7 8 9 10; do
? 加法運(yùn)算
done
遍歷完成之后,退出;
如何生成列表:
{1..100}
`seq [起始數(shù) [步進(jìn)長度]] 結(jié)束數(shù)`
1,...,100
declare -i SUM=0
integer
-x//環(huán)境變量
寫一個腳本:
1、設(shè)定變量FILE的值為/etc/passwd
2、依次向/etc/passwd中的每個用戶問好,并顯示對方的shell,形如: ?
Hello, root, your shell: /bin/bash
#!/bin/bash
for I in `cat /etc/passwd |grep 'bash'`;do
? ? ? ?echo"hello `echo $I |cut -d: -f1` your bash"
done
3、統(tǒng)計一共有多少個用戶
for I in `seq 1 $LINES`; do echo "Hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`"; done
只向默認(rèn)shell為bash的用戶問聲好
寫一個腳本:
1、添加10個用戶user1到user10,密碼同用戶名;但要求只有用戶不存在的情況下才能添加;
#!/bin/bash
if [ $1 == add];then
for I in{1..10};do
? ? ? ?! id user$I &&useradd user$I -puser$I
done
elif [ $1 == del];then
? ? ? ?for I in {1..10};do
? ? ? ? ? ? ? id user$I >/dev/null &&userdel user$I
? ? ? ?done
else
? ? ? ?echo "paramiter wrong"
fi
擴(kuò)展:
接受一個參數(shù):
add: 添加用戶user1..user10
del: 刪除用戶user1..user10
其它:退出
adminusers user1,user2,user3,hello,hi
寫一個腳本:
計算100以內(nèi)所有能被3整除的正整數(shù)的和;
取模,取余:%
3%2=1
100%55=45
寫一個腳本:
let I=$[$I+1]
SUM=$[$SUM+$I]
let SUM+=$I
-=
let I-=1 相當(dāng)于 let I--
++I, --I
*=
/=
%=
測試:
整數(shù)測試:
-eq: 測試兩個整數(shù)是否相等;比如 $A -eq $B
-ne: 測試兩個整數(shù)是否不等;不等,為真;相等,為假;
-gt: 測試一個數(shù)是否大于另一個數(shù);大于,為真;否則,為假;
-lt: 測試一個數(shù)是否小于另一個數(shù);小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當(dāng)前用戶對指定文件是否有讀取權(quán)限;
-w
-x
if [ $# -gt 1 ]; then
組合測試條件
-a: 與關(guān)系
-o: 或關(guān)系
!: 非關(guān)系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
生成隨機(jī)數(shù)?
RANDOM: 0-32768
隨機(jī)數(shù)生成器:熵池
/dev/random:
/dev/urandom:
寫一個腳本,利用RANDOM生成10個隨機(jī)數(shù),并找 出其中的最大值,和最小值;
#!/bin/bash
#
declare -i MAX=0
declare -i MIN=0
for I in {1..10}; do
? MYRAND=$RANDOM
? [ $I -eq 1 ] && MIN=$MYRAND
? if [ $I -le 9 ]; then
? ? echo -n "$MYRAND,"
? else
? ? echo "$MYRAND"
? fi
? [ $MYRAND -gt $MAX ] && MAX=$MYRAND
? [ $MYRAND -lt $MIN ] && MIN=$MYRAND
done
echo $MAX, $MIN
面向過程
控制結(jié)構(gòu)
順序結(jié)構(gòu)
選擇結(jié)構(gòu)
循環(huán)結(jié)構(gòu)
選擇結(jié)構(gòu):
if: 單分支、雙分支、多分支
if CONDITION; then
? statement
? ...
fi
if CONDITION; then
? statement
? ...
else
? statement
? ...
fi
if CONDITION1; then
? statement
? ...
elif CONDITION2; then
? statement
? ...
esle
? statement
? ...
fi
case語句:選擇結(jié)構(gòu)
case SWITCH in?
value1)
? statement
? ...
? ;;
value2)
? statement
? ...
? ;;
*)
? statement
? ...
? ;;
esac
a-z
A-Z
0-9
[abc]
只接受參數(shù)start,stop,restart,status其中之一
#!/bin/bash
#
DEBUG=0
ADD=0
DEL=0
for I in `seq 0 $#`; do
? if [ $# -gt 0 ]; then
?case $1 in
?-v|--verbose)
DEBUG=1
shift ;;
?-h|--help)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 0
;;
?--add)
ADD=1
ADDUSERS=$2
shift 2
;;
?--del)
DEL=1
DELUSERS=$2
shift 2
;;
?*)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 7
;;
? ? esac
? fi
done
if [ $ADD -eq 1 ]; then
? for USER in `echo $ADDUSERS | sed 's@,@ @g'`; do
? ? if id $USER &> /dev/null; then
? ? ? [ $DEBUG -eq 1 ] && echo "$USER exists."
? ? else
? ? ? useradd $USER
? ? ? [ $DEBUG -eq 1 ] && echo "Add user $USER finished."
? ? fi
? done
fi
if [ $DEL -eq 1 ]; then
? for USER in `echo $DELUSERS | sed 's@,@ @g'`; do
? ? if id $USER &> /dev/null; then
? ? ? userdel -r $USER
? ? ? [ $DEBUG -eq 1 ] && echo "Delete $USER finished."
? ? else
? ? ? [ $DEBUG -eq 1 ] && echo "$USER not exist."
? ? fi
? done
fi
練習(xí):寫一個腳本showlogged.sh,其用法格式為:
showlogged.sh -v -c -h|--help
其中,-h選項(xiàng)只能單獨(dú)使用,用于顯示幫助信息;-c選項(xiàng)時,顯示當(dāng)前系統(tǒng)上登錄的所有用戶數(shù);如果同時使用了-v選項(xiàng),則既顯示同時登錄的用戶數(shù),又顯示登錄的用戶的相關(guān)信息;如
Logged users: 4.?
They are:
root ? ? tty2 ? ? ? ? Feb 18 02:41
root ? ? pts/1 ? ? ? ?Mar ?8 08:36 (172.16.100.177)
root ? ? pts/5 ? ? ? ?Mar ?8 07:56 (172.16.100.177)
hadoop ? pts/6 ? ? ? ?Mar ?8 09:16 (172.16.100.177)
#!/bin/bash
#
declare -i SHOWNUM=0
declare -i SHOWUSERS=0
for I in `seq 1 $#`; do
? if [ $# -gt 0 ]; then
? ? case $1 in
? ? -h|--help)
? ? ? echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
? ? ? exit 0 ;;
? ? -v|--verbose)
? ? ? let SHOWUSERS=1
? ? ? shift ;;
? ? -c|--count)
? ? ? let SHOWNUM=1
? ? ? shift ;;
? ? *)
? ? ? echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
? ? ? exit 8 ;;
? ? esac
? fi
done
if [ $SHOWNUM -eq 1 ]; then
? echo "Logged users: `who | wc -l`."
? if [ $SHOWUSERS -eq 1 ]; then
? ? echo "They are:"
? ? who
? fi
fi
腳本編程:
順序結(jié)構(gòu)
選擇結(jié)構(gòu)
if
case
循環(huán)結(jié)構(gòu)
for
while
until
while循環(huán):適用于循環(huán)次數(shù)未知的場景,要有退出條件
語法:
while CONDITION; do
?statement
?...
done
計算100以內(nèi)所有正整數(shù)的和
#!/bin/bash
declare -i I=1
declare -i SUM=0
while [ $I -le 100 ]; do
? let SUM+=$I
? let I++
done
echo $SUM
練習(xí):轉(zhuǎn)換用戶輸入的字符為大寫,除了quit:
#!/bin/bash
#
read -p "Input something: " STRING
while [ $STRING != 'quit' ]; do
? echo $STRING | tr 'a-z' 'A-Z'
? read -p "Input something: " STRING
done
練習(xí):每隔5秒查看hadoop用戶是否登錄,如果登錄,顯示其登錄并退出;否則,顯示當(dāng)前時間,并說明hadoop尚未登錄:
#!/bin/bash
#
who | grep "hadoop" &> /dev/null
RETVAL=$?
while [ $RETVAL -ne 0 ]; do
? echo "`date`, hadoop is not log."?
? sleep 5
? who | grep "hadoop" &> /dev/null
? RETVAL=$?
done
echo "hadoop is logged in."
寫一個腳本:
1) 顯示一個菜單給用戶:?
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
2) 當(dāng)用戶給定選項(xiàng)后顯示相應(yīng)的內(nèi)容;
? ?
擴(kuò)展:
當(dāng)用戶選擇完成,顯示相應(yīng)信息后,不退出;而讓用戶再一次選擇,再次顯示相應(yīng)內(nèi)容;除了用戶使用quit;
#!/bin/bash
#
cat << EOF
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
EOF
read -p "Your choice: " CHOICE
while [ $CHOICE != 'quit' ];do
? case $CHOICE in
? d|D)
? ? echo "Disk usage: "
? ? df -Ph ;;
? m|M)
? ? echo "Memory usage: "
? ? free -m | grep "Mem" ;;
? s|S)
? ? echo "Swap usage: "
? ? free -m | grep "Swap" ;;
? *)
? ? echo "Unknown.." ;;
? esac
read -p "Again, your choice: " CHOICE
done
腳本編程控制結(jié)構(gòu):
順序
選擇
if
case
循環(huán)
for?
while
until
while CONDITION; do
? statment
done
進(jìn)入循環(huán):條件滿足
退出循環(huán):條件不滿足
until CONDITION; do
? statement
? ...
done
進(jìn)入循環(huán):條件不滿足
退出循環(huán):條件滿足
for 變量 in 列表; do?
循環(huán)體
done
for (( expr1 ; expr2 ; expr3 )); do?
? 循環(huán)體
done
寫一個腳本:
1、通過ping命令測試192.168.0.151到192.168.0.254之間的所有主機(jī)是否在線,
如果在線,就顯示"ip is up.",其中的IP要換為真正的IP地址,且以綠色顯示;
如果不在線,就顯示"ip is down.",其中的IP要換為真正的IP地址,且以紅色顯示;
要求:分別使用while,until和for(兩種形式)循環(huán)實(shí)現(xiàn)。
寫一個腳本,完成以下功能:
1、提示用戶輸入一個用戶名;
2、顯示一個菜單給用戶,形如:
cat <<EOF
U|u ?show UID
G|g ?show GID
S|s ?show SHELL
Q|q ?quit
EOF
?#!bin/bash
? ? ? 2 #
? ? ? 3 cat << EOF
? ? ? 4 U|u ?show UID
? ? ? 5 G|g ?show GID
? ? ? 6 S|s ?show SHELL
? ? ? 7 Q|q ?quit
? ? ? 8 EOF
? ? ? 9 read -p "You choice: " CHOICE
? ? ?10 until [ $CHOICE == 'q' -o $CHOICE == 'Q' ]
? ? ?11 do
? ? ?12 case $CHOICE in
? ? ?13 d|D) df -lh;;
? ? ?14 m|M) free -m | grep "^Mem";;
? ? ?15 s|S) free -m | grep "^Swap";;
? ? ?16 *) read -p "You choice,again: " CHOICE;;
? ? ?17 esac
? ? ?18 read -p "You choice: " CHOICE
? ? ?19 done
函數(shù):功能, function
代碼重用:
庫:so
腳本編程之函數(shù):
function: 功能
結(jié)構(gòu)化編程,不能獨(dú)立運(yùn)行,需要調(diào)用時執(zhí)行,可以被多次調(diào)用
定義一個函數(shù):
function FUNCNAME {
? command
}
FUNCNAME() {
? command
}
自定義執(zhí)行狀態(tài)返回值:
return #
0-255
接受參數(shù)的函數(shù):
./a.sh m n?
$1: m
$2: n
sum()
{
echo $1+$2
TWOINT 5 6
$1: 5
$2: 6
練習(xí):寫一個腳本,判定192.168.0.200-192.168.0.254之間的主機(jī)哪些在線。要求:
1、使用函數(shù)來實(shí)現(xiàn)一臺主機(jī)的判定過程;
2、在主程序中來調(diào)用此函數(shù)判定指定范圍內(nèi)的所有主機(jī)的在線情況。
#!/bin/bash
#
PING() {
? for I in {200..254};do
? ? if ping -c 1 -W 1 192.168.0.$I &> /dev/null; then
? ? ? echo "192.168.0.$I is up."
? ? else
? ? ? echo "192.168.0.$I is down."
? ? fi
? done
}
PING
#!/bin/bash
#
PING() {
? ? if ping -c 1 -W 1 $1 &> /dev/null; then
? ? ? echo "$1 is up."
? ? else
? ? ? echo "$1 is down."
? ? fi
}
for I in {200..254}; do
? PING 192.168.0.$I
done
#!/bin/bash
#
PING() {
? ? if ping -c 1 -W 1 $1 &> /dev/null; then
? ? ? return 0
? ? else
? ? ? return 1
? ? fi
}
for I in {200..254}; do
? PING 192.168.0.$I
? if [ $? -eq 0 ]; then
? ? echo "192.168.0.$I is up."
? else
? ? echo "192.168.0.$I is down."
? fi
done
寫一個腳本:使用函數(shù)完成
1、函數(shù)能夠接受一個參數(shù),參數(shù)為用戶名;
? ?判斷一個用戶是否存在
? ?如果存在,就返回此用戶的shell和UID;并返回正常狀態(tài)值;
? ?如果不存在,就說此用戶不存在;并返回錯誤狀態(tài)值;
2、在主程序中調(diào)用函數(shù);
擴(kuò)展1:在主程序中,讓用戶自己輸入用戶名后,傳遞給函數(shù)來進(jìn)行判斷;
擴(kuò)展2:在主程序中,輸入用戶名判斷后不退出腳本,而是提示用戶繼續(xù)輸入下一個用戶名;如果用戶輸入的用戶不存在,請用戶重新輸入;但如果用戶輸入的是q或Q就退出;
#!/bin/bash
#
user () {
if id $1 &> /dev/null ;then
echo "`grep ^$1 ?/etc/passwd | cut -d: -f3,7`"
? ?return 0
else
? ?echo "no $1"
? ? return 1
fi
}
read -p "please input username:" username
until [ $username == q -o $username == Q ]; do
user $username
if [ $? == 0 ];then
read -p "please input again:" username
else
read -p "no $username,please input again:" username
fi
done
函數(shù)也可以接受參數(shù), 即可以向函數(shù)傳遞參數(shù)
函數(shù)接受一個用戶名參數(shù),顯示此用戶的shell和UID;
寫一個函數(shù):接受一命令參數(shù)ls
/bin/ls, /mnt/sysroot/bin/ls
/sbin/ifconfig, /mnt/sysroot/sbin/ifconfig
腳本編程知識點(diǎn):
1、變量中字符的長度:${#VARNAME}
2、變量賦值等:
${parameter:-word}:如果parameter為空或未定義,則變量展開為“word”;否則,展開為parameter的值;
${parameter:+word}:如果parameter為空或未定義,不做任何操作;否則,則展開為“word”值;
${parameter:=word}:如果parameter為空或未定義,則變量展開為“word”,并將展開后的值賦值給parameter;
${parameter:offset}
${parameter:offset:length}:取子串,從offset處的后一個字符開始,取lenth長的子串;
3、腳本配置文件
/etc/rc.d/init.d/服務(wù)腳本
服務(wù)腳本支持配置文件:/etc/sysconfig/服務(wù)腳本同名的配置文件
.conf為配置文件。
#!/bin/bash
#
./root/a.conf ?//把a(bǔ).conf這個文件加載進(jìn)來
local VAR_NAME=//必須用local
a=1
test() {
? a=$[3+4]
}
test
for I in `seq $a 10`; do
? echo $I
done ?
5、命令mktemp
創(chuàng)建臨時文件或目錄
mktemp /tmp/file.XX
-d: 創(chuàng)建為臨時目錄
6、信號
kill -SIG(NAL) PID
1: HUP
2: INT//終止
9: KILL
15: TERM
腳本中,能實(shí)現(xiàn)信號捕捉,但9和15無法捕捉
Ctrl+c: SIGINT
trap命令:
trap 'COMMAND' 信號列表?
7、一行執(zhí)行多個語句,語句間用分號分隔
總結(jié)
以上是生活随笔為你收集整理的linux bash脚本编程知识点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序实战开发视频
- 下一篇: linux 压缩解压归档