linux bash脚本编程知识点
生活随笔
收集整理的這篇文章主要介紹了
linux bash脚本编程知识点
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
bash變量類型:
環境變量
本地變量(局部變量)
位置變量
特殊變量
本地變量:
set VARNAME=VALUE: 作用域為整個bash進程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域為當前代碼段;
環境變量:作用域為當前shell進程及其子進程;
export VARNAM
E=VALUE
VARNAME=VALUE
export VARNAME
“導出”
腳本在執行時會啟動一個子shell進程
命令行中啟動的腳本會繼承當前shell環境變量
系統自動執行的腳本(非命令行啟動)就需要自我定義需要各環境變量
位置變量:
$1, $2, ...
$?: 保存上一個命令的執行狀態返回值;
程序執行,可能有兩類返回值:
程序執行結果
程序狀態返回代碼(0-255)
0: 正確執行
1-255:錯誤執行,1,2,127系統預留;
撤消變量:
unset VARNAME
查看當shell中變量:
set
查看當前shell中的環境變量:
printenv
env
export
腳本:命令的堆砌,按實際需要,結合命令流程控制機制實現的源程序
shebang: 魔數
#!/bin/bash
# 注釋行,不執行
/dev/null: 軟件設備, bit bucket,數據黑洞
腳本在執行時會啟動一個子shell進程;
命令行中啟動的腳本會繼承當前shell環境變量;
;
練習:寫一個腳本,完成以下任務
1、添加5個用戶, user1,..., user5
2、每個用戶的密碼同用戶名,而且要求,添加密碼完成后不顯示passwd命令的執行結果信息;
3、每個用戶添加完成后,都要顯示用戶某某已經成功添加;
useradd user1
echo "user1" | passwd --stdin user1 &> /dev/null
echo "Add user1 successfully."
條件判斷:
如果用戶不存在
添加用戶,給密碼并顯示添加成功;
否則
顯示如果已經沒在,沒有添加;
bash中如何實現條件判斷?
條件測試類型:
整數測試
字符測試
文件測試
條件測試的表達式:
[ expression ]
[[ expression ]]
test expression
整數比較:
-eq: 測試兩個整數是否相等;比如 $A -eq $B
-ne: 測試兩個整數是否不等;不等,為真;相等,為假;
-gt: 測試一個數是否大于另一個數;大于,為真;否則,為假;
-lt: 測試一個數是否小于另一個數;小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
命令的間邏輯關系:
邏輯與: &&
第一個條件為假時,第二條件不用再判斷,最終結果已經有;
第一個條件為真時,第二條件必須得判斷;
邏輯或: ||
如果用戶user6不存在,就添加用戶user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab文件的行數大于100,就顯示好大的文件;
[ `wc -l /etc/inittab | cut -d' ' -f1` -gt 100 ] && echo "Large file."
變量名稱:
1、只能包含字母、數字和下劃線,并且不能數字開頭;
2、不應該跟系統中已有的環境變量重名;
3、最好做到見名知義;
如果用戶存在,就顯示用戶已存在;否則,就添加此用戶;
id user1 && echo "user1 exists." || useradd user1
如果用戶不存在,就添加;否則,顯示其已經存在;
! id user1 && useradd user1 || echo "user1 exists."
如果用戶不存在,添加并且給密碼;否則,顯示其已經存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdin user1 || echo "user1 exists."
練習,寫一個腳本,完成以下要求:
1、添加3個用戶user1, user2, user3;但要先判斷用戶是否存在,不存在而后再添加;
2、添加完成后,顯示一共添加了幾個用戶;當然,不能包括因為事先存在而沒有添加的;
3、最后顯示當前系統上共有多少個用戶;
如果 UID為0;那么
? 顯示為管理員
否則
? 顯示為普通用戶
??
NAME=user16
USERID=`id -u $NAME`
if [ $USERID -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi//結束
NAME=user16
if [ `id -u $NAME` -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi
練習:寫一個腳本
判斷當前系統上是否有用戶的默認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
練習:寫一個腳本
給定一個文件,比如/etc/inittab?
判斷這個文件中是否有空白行;
如果有,則顯示其空白行數;否則,顯示沒有空白行。
#!/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
練習:寫一個腳本
給定一個用戶,判斷其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
進一步要求:不使用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
練習:寫一個腳本
給定一個用戶,獲取其密碼警告期限;
而后判斷用戶密碼使用期限是否已經小于警告期限;
提示:計算方法,最長使用期限減去已經使用的天數即為剩余使用期限;
如果小于,則顯示“Warning”;否則,就顯示“OK”。
圓整:丟棄小數點后的所有內容
#!/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
練習:寫一個腳本
判定命令歷史中歷史命令的總條目是否大于1000;如果大于,則顯示“Some command will gone.”;否則顯示“OK”。
shell中如何進行算術運算:
A=3
B=6
1、let 算術運算表達式
let C=$A+$B
2、$[算術運算表達式]
C=$[$A+$B]
3、$((算術運算表達式))
C=$(($A+$B))
4、expr 算術運算表達式,表達式中各操作數及運算符之間要有空格,而且要使用命令引用
C=`expr $A + $B`
條件判斷,控制結構:
單分支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中常用的條件測試有三種:
整數測試:
-eq: 測試兩個整數是否相等;比如 $A -eq $B
-ne: 測試兩個整數是否不等;不等,為真;相等,為假;
-gt: 測試一個數是否大于另一個數;大于,為真;否則,為假;
-lt: 測試一個數是否小于另一個數;小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
INT1=63
INT2=77
[ $INT1 -eq $INI2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2 ?
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當前用戶對指定文件是否有讀取權限;
-w
-x
[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
練習:寫一個腳本
給定一個文件:
如果是一個普通文件,就顯示之;
如果是一個目錄,亦顯示之;
否則,此為無法識別之文件;
定義腳本退出狀態碼
exit: 退出腳本
exit #
如果腳本沒有明確定義退出狀態碼,那么,最后執行的一條命令的退出碼即為腳本的退出狀態碼;
測試腳本是否有語法錯誤:
bash -n 腳本
bash -x 腳本:單步執行
bash變量的類型:
本地變量:
set VARNAME=VALUE: 作用域為整個bash進程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域為當前代碼段;
環境變量:作用域為當前shell進程及其子進程;
export VARNAME=VALUE
VARNAME=VALUE
export VARNAME
“導出”
腳本在執行時會啟動一個子shell進程
命令行中啟動的腳本會繼承當前shell環境變量
系統自動執行的腳本(非命令行啟動)就需要自我定義需要各環境變量
位置變量:?
$1, $2, ...
shift
特殊變量:
$?
$#:參數的個數
$*: 參數列表
$@:參數列表
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
練習:寫一腳本
能接受一個參數(文件路徑)
判定:此參數如果是一個存在的文件,就顯示“OK.”;否則就顯示"No such file."
練習:寫一個腳本
給腳本傳遞兩個參數(整數);
顯示此兩者之和,之乘積;
#!/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]."
練習:寫一個腳本,完成以下任務
1、使用一個變量保存一個用戶名;
2、刪除此變量中的用戶,且一并刪除其家目錄;
3、顯示“用戶刪除完成”類的信息
bash:?
引用變量:${VARNAME}, 括號有時可省略。
整型,8bit: 256
0-255, 溢出
變量:
1,10000
10:16bit
10: 1010, 8bit
編程能力:
腳本編程
#abc
# hello world
? ?# hi world
練習:
傳遞一個用戶名參數給腳本,判斷此用戶的用戶名跟其基本組的組名是否一致,并將結果顯示出來。
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
練習:寫一個腳本
傳遞一個參數(單字符就行)給腳本,如參數為q,就退出腳本;否則,就顯示用戶的參數;
練習:寫一個腳本
傳遞一個參數(單字符就行)給腳本,如參數為q、Q、quit或Quit,就退出腳本;否則,就顯示用戶的參數;
#!/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
練習:
if [ $# -lt 2 ];
傳遞三個參數給腳本,第一個為整數,第二個為算術運算符,第三個為整數,將計算結果顯示出來,要求保留兩位精度。形如:
./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 ? //結果為5.04
練習:
傳遞3個參數給腳本,參數均為用戶名。將此些用戶的帳號信息提取出來后放置于/tmp/testusers.txt文件中,并要求每一行行首有行號。
egrep “$1|$2|$3” /etc/passwd >>/tmp/a
cat ?n /tmp/a > /tmp/test0
rm ?rf a
寫一個腳本:
判斷當前主機的CPU生產商,其信息在/proc/cpuinfo文件中vendor id一行中。
如果其生產商為AuthenticAMD,就顯示其為AMD公司;
如果其生產商為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
寫一個腳本:
給腳本傳遞三個整數,判斷其中的最大數和最小數,并顯示出來。
MAX=0
MAX -eq $1
MAX=$1
MAX -lt $2
MAX=$2
例:比較三個數的大小
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?!?
循環:進入條件,退出條件
for
while
until
for 變量 in 列表; do
? 循環體
done
for I in 1 2 3 4 5 6 7 8 9 10; do
? 加法運算
done
遍歷完成之后,退出;
如何生成列表:
{1..100}
`seq [起始數 [步進長度]] 結束數`
1,...,100
declare -i SUM=0
integer
-x//環境變量
寫一個腳本:
1、設定變量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、統計一共有多少個用戶
for I in `seq 1 $LINES`; do echo "Hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`"; done
只向默認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
擴展:
接受一個參數:
add: 添加用戶user1..user10
del: 刪除用戶user1..user10
其它:退出
adminusers user1,user2,user3,hello,hi
寫一個腳本:
計算100以內所有能被3整除的正整數的和;
取模,取余:%
3%2=1
100%55=45
寫一個腳本:
let I=$[$I+1]
SUM=$[$SUM+$I]
-=
let I-=1 相當于 let I--
++I, --I
*=
/=
%=
測試:
整數測試:
-eq: 測試兩個整數是否相等;比如 $A -eq $B
-ne: 測試兩個整數是否不等;不等,為真;相等,為假;
-gt: 測試一個數是否大于另一個數;大于,為真;否則,為假;
-lt: 測試一個數是否小于另一個數;小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當前用戶對指定文件是否有讀取權限;
-w
-x
if [ $# -gt 1 ]; then
組合測試條件
-a: 與關系
-o: 或關系
!: 非關系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
生成隨機數?
RANDOM: 0-32768
隨機數生成器:熵池
/dev/random:
/dev/urandom:
寫一個腳本,利用RANDOM生成10個隨機數,并找 出其中的最大值,和最小值;
#!/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
面向過程
控制結構
順序結構
選擇結構
循環結構
選擇結構:
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語句:選擇結構
case SWITCH in?
value1)
? statement
? ...
? ;;
value2)
? statement
? ...
? ;;
*)
? statement
? ...
? ;;
esac
a-z
A-Z
0-9
[abc]
只接受參數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
練習:寫一個腳本showlogged.sh,其用法格式為:
showlogged.sh -v -c -h|--help
其中,-h選項只能單獨使用,用于顯示幫助信息;-c選項時,顯示當前系統上登錄的所有用戶數;如果同時使用了-v選項,則既顯示同時登錄的用戶數,又顯示登錄的用戶的相關信息;如
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
腳本編程:
順序結構
選擇結構
if
case
循環結構
for
while
until
while循環:適用于循環次數未知的場景,要有退出條件
語法:
while CONDITION; do
?statement
?...
done
計算100以內所有正整數的和
#!/bin/bash
declare -i I=1
declare -i SUM=0
while [ $I -le 100 ]; do
? let SUM+=$I
? let I++
done
echo $SUM
練習:轉換用戶輸入的字符為大寫,除了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
練習:每隔5秒查看hadoop用戶是否登錄,如果登錄,顯示其登錄并退出;否則,顯示當前時間,并說明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) 當用戶給定選項后顯示相應的內容;
? ?
擴展:
當用戶選擇完成,顯示相應信息后,不退出;而讓用戶再一次選擇,再次顯示相應內容;除了用戶使用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
腳本編程控制結構:
順序
選擇
if
case
循環
for?
while
until
while CONDITION; do
? statment
done
進入循環:條件滿足
退出循環:條件不滿足
until CONDITION; do
? statement
? ...
done
進入循環:條件不滿足
退出循環:條件滿足
for 變量 in 列表; do?
循環體
done
for (( expr1 ; expr2 ; expr3 )); do?
? 循環體
done
寫一個腳本:
1、通過ping命令測試192.168.0.151到192.168.0.254之間的所有主機是否在線,
如果在線,就顯示"ip is up.",其中的IP要換為真正的IP地址,且以綠色顯示;
如果不在線,就顯示"ip is down.",其中的IP要換為真正的IP地址,且以紅色顯示;
要求:分別使用while,until和for(兩種形式)循環實現。
寫一個腳本,完成以下功能:
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
函數:功能, function
代碼重用:
庫:so
腳本編程之函數:
function: 功能
結構化編程,不能獨立運行,需要調用時執行,可以被多次調用
定義一個函數:
function FUNCNAME {
? command
}
FUNCNAME() {
? command
}
自定義執行狀態返回值:
return #
0-255
接受參數的函數:
./a.sh m n?
$1: m
$2: n
sum()
{
echo $1+$2
TWOINT 5 6
$1: 5
$2: 6
練習:寫一個腳本,判定192.168.0.200-192.168.0.254之間的主機哪些在線。要求:
1、使用函數來實現一臺主機的判定過程;
2、在主程序中來調用此函數判定指定范圍內的所有主機的在線情況。
#!/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
寫一個腳本:使用函數完成
1、函數能夠接受一個參數,參數為用戶名;
? ?判斷一個用戶是否存在
? ?如果存在,就返回此用戶的shell和UID;并返回正常狀態值;
? ?如果不存在,就說此用戶不存在;并返回錯誤狀態值;
2、在主程序中調用函數;
擴展1:在主程序中,讓用戶自己輸入用戶名后,傳遞給函數來進行判斷;
擴展2:在主程序中,輸入用戶名判斷后不退出腳本,而是提示用戶繼續輸入下一個用戶名;如果用戶輸入的用戶不存在,請用戶重新輸入;但如果用戶輸入的是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
函數也可以接受參數, 即可以向函數傳遞參數
函數接受一個用戶名參數,顯示此用戶的shell和UID;
寫一個函數:接受一命令參數ls
/bin/ls, /mnt/sysroot/bin/ls
/sbin/ifconfig, /mnt/sysroot/sbin/ifconfig
腳本編程知識點:
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/服務腳本
服務腳本支持配置文件:/etc/sysconfig/服務腳本同名的配置文件
.conf為配置文件。
#!/bin/bash
#
./root/a.conf ?//把a.conf這個文件加載進來
local VAR_NAME=//必須用local
a=1
test() {
? a=$[3+4]
}
test
for I in `seq $a 10`; do
? echo $I
done ?
5、命令mktemp
創建臨時文件或目錄
mktemp /tmp/file.XX
-d: 創建為臨時目錄
6、信號
kill -SIG(NAL) PID
1: HUP
2: INT//終止
9: KILL
15: TERM
腳本中,能實現信號捕捉,但9和15無法捕捉
Ctrl+c: SIGINT
trap命令:
trap 'COMMAND' 信號列表?
7、一行執行多個語句,語句間用分號分隔
環境變量
本地變量(局部變量)
位置變量
特殊變量
本地變量:
set VARNAME=VALUE: 作用域為整個bash進程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域為當前代碼段;
環境變量:作用域為當前shell進程及其子進程;
export VARNAM
E=VALUE
VARNAME=VALUE
export VARNAME
“導出”
腳本在執行時會啟動一個子shell進程
命令行中啟動的腳本會繼承當前shell環境變量
系統自動執行的腳本(非命令行啟動)就需要自我定義需要各環境變量
位置變量:
$1, $2, ...
$?: 保存上一個命令的執行狀態返回值;
程序執行,可能有兩類返回值:
程序執行結果
程序狀態返回代碼(0-255)
0: 正確執行
1-255:錯誤執行,1,2,127系統預留;
撤消變量:
unset VARNAME
查看當shell中變量:
set
查看當前shell中的環境變量:
printenv
env
export
腳本:命令的堆砌,按實際需要,結合命令流程控制機制實現的源程序
shebang: 魔數
#!/bin/bash
# 注釋行,不執行
/dev/null: 軟件設備, bit bucket,數據黑洞
腳本在執行時會啟動一個子shell進程;
命令行中啟動的腳本會繼承當前shell環境變量;
;
練習:寫一個腳本,完成以下任務
1、添加5個用戶, user1,..., user5
2、每個用戶的密碼同用戶名,而且要求,添加密碼完成后不顯示passwd命令的執行結果信息;
3、每個用戶添加完成后,都要顯示用戶某某已經成功添加;
useradd user1
echo "user1" | passwd --stdin user1 &> /dev/null
echo "Add user1 successfully."
條件判斷:
如果用戶不存在
添加用戶,給密碼并顯示添加成功;
否則
顯示如果已經沒在,沒有添加;
bash中如何實現條件判斷?
條件測試類型:
整數測試
字符測試
文件測試
條件測試的表達式:
[ expression ]
[[ expression ]]
test expression
整數比較:
-eq: 測試兩個整數是否相等;比如 $A -eq $B
-ne: 測試兩個整數是否不等;不等,為真;相等,為假;
-gt: 測試一個數是否大于另一個數;大于,為真;否則,為假;
-lt: 測試一個數是否小于另一個數;小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
命令的間邏輯關系:
邏輯與: &&
第一個條件為假時,第二條件不用再判斷,最終結果已經有;
第一個條件為真時,第二條件必須得判斷;
邏輯或: ||
如果用戶user6不存在,就添加用戶user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab文件的行數大于100,就顯示好大的文件;
[ `wc -l /etc/inittab | cut -d' ' -f1` -gt 100 ] && echo "Large file."
變量名稱:
1、只能包含字母、數字和下劃線,并且不能數字開頭;
2、不應該跟系統中已有的環境變量重名;
3、最好做到見名知義;
如果用戶存在,就顯示用戶已存在;否則,就添加此用戶;
id user1 && echo "user1 exists." || useradd user1
如果用戶不存在,就添加;否則,顯示其已經存在;
! id user1 && useradd user1 || echo "user1 exists."
如果用戶不存在,添加并且給密碼;否則,顯示其已經存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdin user1 || echo "user1 exists."
練習,寫一個腳本,完成以下要求:
1、添加3個用戶user1, user2, user3;但要先判斷用戶是否存在,不存在而后再添加;
2、添加完成后,顯示一共添加了幾個用戶;當然,不能包括因為事先存在而沒有添加的;
3、最后顯示當前系統上共有多少個用戶;
如果 UID為0;那么
? 顯示為管理員
否則
? 顯示為普通用戶
??
NAME=user16
USERID=`id -u $NAME`
if [ $USERID -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi//結束
NAME=user16
if [ `id -u $NAME` -eq 0 ]; then
? echo "Admin"
else
? echo "common user."
fi
練習:寫一個腳本
判斷當前系統上是否有用戶的默認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
練習:寫一個腳本
給定一個文件,比如/etc/inittab?
判斷這個文件中是否有空白行;
如果有,則顯示其空白行數;否則,顯示沒有空白行。
#!/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
練習:寫一個腳本
給定一個用戶,判斷其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
進一步要求:不使用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
練習:寫一個腳本
給定一個用戶,獲取其密碼警告期限;
而后判斷用戶密碼使用期限是否已經小于警告期限;
提示:計算方法,最長使用期限減去已經使用的天數即為剩余使用期限;
如果小于,則顯示“Warning”;否則,就顯示“OK”。
圓整:丟棄小數點后的所有內容
#!/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
練習:寫一個腳本
判定命令歷史中歷史命令的總條目是否大于1000;如果大于,則顯示“Some command will gone.”;否則顯示“OK”。
shell中如何進行算術運算:
A=3
B=6
1、let 算術運算表達式
let C=$A+$B
2、$[算術運算表達式]
C=$[$A+$B]
3、$((算術運算表達式))
C=$(($A+$B))
4、expr 算術運算表達式,表達式中各操作數及運算符之間要有空格,而且要使用命令引用
C=`expr $A + $B`
條件判斷,控制結構:
單分支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中常用的條件測試有三種:
整數測試:
-eq: 測試兩個整數是否相等;比如 $A -eq $B
-ne: 測試兩個整數是否不等;不等,為真;相等,為假;
-gt: 測試一個數是否大于另一個數;大于,為真;否則,為假;
-lt: 測試一個數是否小于另一個數;小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
INT1=63
INT2=77
[ $INT1 -eq $INI2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2 ?
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當前用戶對指定文件是否有讀取權限;
-w
-x
[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
練習:寫一個腳本
給定一個文件:
如果是一個普通文件,就顯示之;
如果是一個目錄,亦顯示之;
否則,此為無法識別之文件;
定義腳本退出狀態碼
exit: 退出腳本
exit #
如果腳本沒有明確定義退出狀態碼,那么,最后執行的一條命令的退出碼即為腳本的退出狀態碼;
測試腳本是否有語法錯誤:
bash -n 腳本
bash -x 腳本:單步執行
bash變量的類型:
本地變量:
set VARNAME=VALUE: 作用域為整個bash進程;
引用變量 $(varname)
局部變量:
local VARNAME=VALUE:作用域為當前代碼段;
環境變量:作用域為當前shell進程及其子進程;
export VARNAME=VALUE
VARNAME=VALUE
export VARNAME
“導出”
腳本在執行時會啟動一個子shell進程
命令行中啟動的腳本會繼承當前shell環境變量
系統自動執行的腳本(非命令行啟動)就需要自我定義需要各環境變量
位置變量:?
$1, $2, ...
shift
特殊變量:
$?
$#:參數的個數
$*: 參數列表
$@:參數列表
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
練習:寫一腳本
能接受一個參數(文件路徑)
判定:此參數如果是一個存在的文件,就顯示“OK.”;否則就顯示"No such file."
練習:寫一個腳本
給腳本傳遞兩個參數(整數);
顯示此兩者之和,之乘積;
#!/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]."
練習:寫一個腳本,完成以下任務
1、使用一個變量保存一個用戶名;
2、刪除此變量中的用戶,且一并刪除其家目錄;
3、顯示“用戶刪除完成”類的信息
bash:?
引用變量:${VARNAME}, 括號有時可省略。
整型,8bit: 256
0-255, 溢出
變量:
1,10000
10:16bit
10: 1010, 8bit
編程能力:
腳本編程
#abc
# hello world
? ?# hi world
練習:
傳遞一個用戶名參數給腳本,判斷此用戶的用戶名跟其基本組的組名是否一致,并將結果顯示出來。
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
練習:寫一個腳本
傳遞一個參數(單字符就行)給腳本,如參數為q,就退出腳本;否則,就顯示用戶的參數;
練習:寫一個腳本
傳遞一個參數(單字符就行)給腳本,如參數為q、Q、quit或Quit,就退出腳本;否則,就顯示用戶的參數;
#!/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
練習:
if [ $# -lt 2 ];
傳遞三個參數給腳本,第一個為整數,第二個為算術運算符,第三個為整數,將計算結果顯示出來,要求保留兩位精度。形如:
./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 ? //結果為5.04
練習:
傳遞3個參數給腳本,參數均為用戶名。將此些用戶的帳號信息提取出來后放置于/tmp/testusers.txt文件中,并要求每一行行首有行號。
egrep “$1|$2|$3” /etc/passwd >>/tmp/a
cat ?n /tmp/a > /tmp/test0
rm ?rf a
寫一個腳本:
判斷當前主機的CPU生產商,其信息在/proc/cpuinfo文件中vendor id一行中。
如果其生產商為AuthenticAMD,就顯示其為AMD公司;
如果其生產商為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
寫一個腳本:
給腳本傳遞三個整數,判斷其中的最大數和最小數,并顯示出來。
MAX=0
MAX -eq $1
MAX=$1
MAX -lt $2
MAX=$2
例:比較三個數的大小
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?!?
循環:進入條件,退出條件
for
while
until
for 變量 in 列表; do
? 循環體
done
for I in 1 2 3 4 5 6 7 8 9 10; do
? 加法運算
done
遍歷完成之后,退出;
如何生成列表:
{1..100}
`seq [起始數 [步進長度]] 結束數`
1,...,100
declare -i SUM=0
integer
-x//環境變量
寫一個腳本:
1、設定變量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、統計一共有多少個用戶
for I in `seq 1 $LINES`; do echo "Hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`"; done
只向默認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
擴展:
接受一個參數:
add: 添加用戶user1..user10
del: 刪除用戶user1..user10
其它:退出
adminusers user1,user2,user3,hello,hi
寫一個腳本:
計算100以內所有能被3整除的正整數的和;
取模,取余:%
3%2=1
100%55=45
寫一個腳本:
let I=$[$I+1]
SUM=$[$SUM+$I]
let SUM+=$I
-=
let I-=1 相當于 let I--
++I, --I
*=
/=
%=
測試:
整數測試:
-eq: 測試兩個整數是否相等;比如 $A -eq $B
-ne: 測試兩個整數是否不等;不等,為真;相等,為假;
-gt: 測試一個數是否大于另一個數;大于,為真;否則,為假;
-lt: 測試一個數是否小于另一個數;小于,為真;否則,為假;
-ge: 大于或等于
-le:小于或等于
字符測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字符串 是否為空,空則真,不空則假
-z string: 測試指定字符串是否不空,不空為真,空則為假
文件測試:
-e FILE:測試文件是否存在
-f FILE: 測試文件是否為普通文件
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試當前用戶對指定文件是否有讀取權限;
-w
-x
if [ $# -gt 1 ]; then
組合測試條件
-a: 與關系
-o: 或關系
!: 非關系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
生成隨機數?
RANDOM: 0-32768
隨機數生成器:熵池
/dev/random:
/dev/urandom:
寫一個腳本,利用RANDOM生成10個隨機數,并找 出其中的最大值,和最小值;
#!/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
面向過程
控制結構
順序結構
選擇結構
循環結構
選擇結構:
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語句:選擇結構
case SWITCH in?
value1)
? statement
? ...
? ;;
value2)
? statement
? ...
? ;;
*)
? statement
? ...
? ;;
esac
a-z
A-Z
0-9
[abc]
只接受參數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
練習:寫一個腳本showlogged.sh,其用法格式為:
showlogged.sh -v -c -h|--help
其中,-h選項只能單獨使用,用于顯示幫助信息;-c選項時,顯示當前系統上登錄的所有用戶數;如果同時使用了-v選項,則既顯示同時登錄的用戶數,又顯示登錄的用戶的相關信息;如
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
腳本編程:
順序結構
選擇結構
if
case
循環結構
for
while
until
while循環:適用于循環次數未知的場景,要有退出條件
語法:
while CONDITION; do
?statement
?...
done
計算100以內所有正整數的和
#!/bin/bash
declare -i I=1
declare -i SUM=0
while [ $I -le 100 ]; do
? let SUM+=$I
? let I++
done
echo $SUM
練習:轉換用戶輸入的字符為大寫,除了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
練習:每隔5秒查看hadoop用戶是否登錄,如果登錄,顯示其登錄并退出;否則,顯示當前時間,并說明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) 當用戶給定選項后顯示相應的內容;
? ?
擴展:
當用戶選擇完成,顯示相應信息后,不退出;而讓用戶再一次選擇,再次顯示相應內容;除了用戶使用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
腳本編程控制結構:
順序
選擇
if
case
循環
for?
while
until
while CONDITION; do
? statment
done
進入循環:條件滿足
退出循環:條件不滿足
until CONDITION; do
? statement
? ...
done
進入循環:條件不滿足
退出循環:條件滿足
for 變量 in 列表; do?
循環體
done
for (( expr1 ; expr2 ; expr3 )); do?
? 循環體
done
寫一個腳本:
1、通過ping命令測試192.168.0.151到192.168.0.254之間的所有主機是否在線,
如果在線,就顯示"ip is up.",其中的IP要換為真正的IP地址,且以綠色顯示;
如果不在線,就顯示"ip is down.",其中的IP要換為真正的IP地址,且以紅色顯示;
要求:分別使用while,until和for(兩種形式)循環實現。
寫一個腳本,完成以下功能:
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
函數:功能, function
代碼重用:
庫:so
腳本編程之函數:
function: 功能
結構化編程,不能獨立運行,需要調用時執行,可以被多次調用
定義一個函數:
function FUNCNAME {
? command
}
FUNCNAME() {
? command
}
自定義執行狀態返回值:
return #
0-255
接受參數的函數:
./a.sh m n?
$1: m
$2: n
sum()
{
echo $1+$2
TWOINT 5 6
$1: 5
$2: 6
練習:寫一個腳本,判定192.168.0.200-192.168.0.254之間的主機哪些在線。要求:
1、使用函數來實現一臺主機的判定過程;
2、在主程序中來調用此函數判定指定范圍內的所有主機的在線情況。
#!/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
寫一個腳本:使用函數完成
1、函數能夠接受一個參數,參數為用戶名;
? ?判斷一個用戶是否存在
? ?如果存在,就返回此用戶的shell和UID;并返回正常狀態值;
? ?如果不存在,就說此用戶不存在;并返回錯誤狀態值;
2、在主程序中調用函數;
擴展1:在主程序中,讓用戶自己輸入用戶名后,傳遞給函數來進行判斷;
擴展2:在主程序中,輸入用戶名判斷后不退出腳本,而是提示用戶繼續輸入下一個用戶名;如果用戶輸入的用戶不存在,請用戶重新輸入;但如果用戶輸入的是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
函數也可以接受參數, 即可以向函數傳遞參數
函數接受一個用戶名參數,顯示此用戶的shell和UID;
寫一個函數:接受一命令參數ls
/bin/ls, /mnt/sysroot/bin/ls
/sbin/ifconfig, /mnt/sysroot/sbin/ifconfig
腳本編程知識點:
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/服務腳本
服務腳本支持配置文件:/etc/sysconfig/服務腳本同名的配置文件
.conf為配置文件。
#!/bin/bash
#
./root/a.conf ?//把a.conf這個文件加載進來
local VAR_NAME=//必須用local
a=1
test() {
? a=$[3+4]
}
test
for I in `seq $a 10`; do
? echo $I
done ?
5、命令mktemp
創建臨時文件或目錄
mktemp /tmp/file.XX
-d: 創建為臨時目錄
6、信號
kill -SIG(NAL) PID
1: HUP
2: INT//終止
9: KILL
15: TERM
腳本中,能實現信號捕捉,但9和15無法捕捉
Ctrl+c: SIGINT
trap命令:
trap 'COMMAND' 信號列表?
7、一行執行多個語句,語句間用分號分隔
總結
以上是生活随笔為你收集整理的linux bash脚本编程知识点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序实战开发视频
- 下一篇: linux 其他常用命令