終端,附著在終端的接口程序
GUI:KDE,GNome ,Xfce
CLI : /etc/shells
bash
zsh
fish
bash的特性:
命令行展開: ~,{}
命令別名: alias, unalias
命令歷史: history
文件名通配:glob
快捷鍵:Ctrl+a,e , u , k ,l
命令補(bǔ)全: $PATH
路徑補(bǔ)全:
bash特性之:命令hash
緩存此前命令的查找結(jié)果:key-value
key:搜索鍵
value: 值
hash命令:
hash:列出
hash -d COMMAND:刪除
hash -r :清空
bash的特性之:變量
程序:指令+數(shù)據(jù)
指令:由程序文件提供
數(shù)據(jù):IO設(shè)備、文件、管道、變量
程序:算法+數(shù)據(jù)結(jié)構(gòu)
變量名+指向的內(nèi)存空間
變量賦值:name=value
變量類型:存儲格式、表示數(shù)據(jù)范圍、參與的運算
編程語言:
強(qiáng)類型變量:
弱類型變量:
bash把所有變量統(tǒng)統(tǒng)視作字符型;
bash中的變量無需事先聲明;相當(dāng)于,把聲明和復(fù)制過程同時實現(xiàn)
聲明:類型,變量名
變量替換:把變量名出現(xiàn)的位置替換為其所指向的內(nèi)存空間中的數(shù)據(jù)
變量引用: ${var_name} ,$var_name
變量名:變量名只能包含數(shù)字、字母和下劃線,而且不能以數(shù)字開頭,不能使用程序的保留字段:if while for then
變量:見名知義,命名機(jī)制遵循某種法則
bash變量類型:
本地變量:作用域僅為當(dāng)前shell進(jìn)程
環(huán)境變量:作用域僅為當(dāng)前shell進(jìn)程及其子進(jìn)程
局部變量:作用域僅為代碼片段(函數(shù)上下文)
位置參數(shù)變量:當(dāng)執(zhí)行腳本的shell進(jìn)程傳遞的參數(shù)
$1,$2...
shift
特殊變量:shell內(nèi)置的有特殊功能的變量
$?:上一個命令的執(zhí)行狀態(tài)返回值
0:成功
1-255:失敗
$#:參數(shù)的個數(shù)
$*:參數(shù)列表
$@: 參數(shù)列表
本地變量:
變量賦值:name=value
變量引用:${name}, $name
"":變量為會替換為其值
'':變量名不會替換為其值
查看變量:set
撤銷變量:unset name
注意:此處非變量引用
環(huán)境變量:
變量賦值:
(1)export name=value
(2)name=value
export name(3)declare -x name=value
(4)name=value
declare -x name
變量引用:${name}, $name
注意:bash內(nèi)嵌了許多環(huán)境變量(通常為全大寫字符),用于定義bash的工作環(huán)境
PATH ,HISTFILE, HISTSIZE, HISTFILESIZE,HISTCONTROL, SHELL ,HOME ,UID ,PWD ,OLDPWD
查看環(huán)境變量:export ,declare -x, printenv ,env
撤銷環(huán)境變量:unset name
只讀變量:
(1)declare -r name
(2)readonly name
只讀變量無法重新賦值,并且不支持撤銷;存活時間為當(dāng)前shell進(jìn)程的生命周期,隨shell進(jìn)程終止而終止
bash特性之多命令執(zhí)行:
COMMAND1; COMMAND2; COMMAND3; ....
邏輯運算:
真(true, yes, on ,1)
假(false, no , off , 0)
與:
1&&1=1
1&&0=0
0&&1=0
0&&0=0
或:
1 || 1=1
1 || 0=1
0 || 1=1
0 || 0=0
非:
!1=0
!0=1
短路法則:
COMMAND1 && COMMAND2
COMMAND1為“假”,則COMMAND2不會再執(zhí)行
否則,COMMAND1為“真”,則COMMAND2必須執(zhí)行
COMMAND1 || COMMAND2
COMMAND1為“真”,則COMMAND2不會再執(zhí)行
否則,COMMAND1為“假”,則COMMAND2必須執(zhí)行例:id $username || useradd $useradd
練習(xí)1:
1、添加3個用戶user1,user2,user3,先判斷用戶是否存在,不存在而后再添加
2、顯示當(dāng)前系統(tǒng)上共有多少個用戶
#!/bin/bash
for i in user1 user2 user3
do
! id $i &> /dev/null && useradd $i && echo $i | passwd --stdin $i &> /dev/null || echo "$i is exists"
done
sum=`wc -l /etc/passwd | cut -d' ' -f1`
echo "$sum /etc/passwd users"
shell腳本編程:
編程語言的分類:根據(jù)運行方式
編譯運行:源代碼-->編譯器(編譯)-->程序文件
解釋運行:源代碼-->運行時啟動解釋器,由解釋器邊解釋邊運行
根據(jù)其編程過程中功能的實現(xiàn)是調(diào)用庫還是調(diào)用外部的程序文件:
shell腳本編程:
利用系統(tǒng)上的命令及編程組件進(jìn)行編程
完整編程:
利用庫和編程組件進(jìn)行編程
編程模型:過程式編程語言,面向?qū)ο蟮木幊陶Z言
程序+指令+數(shù)據(jù)
過程式:以指令為中心來組織代碼,數(shù)據(jù)是服務(wù)于代碼;
順序執(zhí)行:
選擇執(zhí)行:
循環(huán)執(zhí)行:
代表:c語言,bash
對象式:以數(shù)據(jù)為中心來組織代碼,圍繞數(shù)據(jù)來組織指令;
類(class):實例化對象,method:
代表:java,c++, python
shell腳本編程:過程式編程,解釋運行,依賴于外部程序程序文件運行;
如何寫shell腳本:
腳本文件的第一行,頂格:給出shebang, 解析器路徑,用于指明解析執(zhí)行當(dāng)前腳本解析器程序文件
常見的解析器:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
文本編輯器:nano
行編輯器:sed
全屏幕編程器:nano, vi , vim
shell腳本是什么?
命令的堆積:
但很多命令不具有冪等性,需要用程序邏輯來判斷運行條件十分滿足,以避免其運行中發(fā)生錯誤;
運行腳本:
(1)賦予執(zhí)行權(quán)限,并直接運行此程序文件;
chmod +x /path/to/script_file
/path/to/script_file
(2)直接運行解析器,將腳本以命令行參數(shù)傳遞給解釋器程序
bash/path/to/script_file
注意:腳本中的空白行會被解釋器忽略
腳本中,除了shebang,余下所有#開頭的行,都會被視作注釋而被忽略;此即為注釋行
shell腳本的運行是通過運行一個子shell進(jìn)程實現(xiàn)的
練習(xí)1:寫一個腳本,實現(xiàn)如下功能:
(1)顯示/etc目錄下所有以大寫P或小寫p開頭的文件或目錄本身
(2)顯示/var目錄下所有文件或者目錄本身,并將顯示結(jié)果中的小寫字母轉(zhuǎn)換為大寫顯示
(3)創(chuàng)建臨時文件/tmp/myfile.XXXX
bash的配置文件:
兩類:
profile類:為交互式登錄的shell提供配置
bashrc類:為非交互式登錄的shell提供配置
登錄類型:
交互式登錄shell進(jìn)程:
直接通過某終端輸入賬號和密碼后登錄打開的shell進(jìn)程;
使用su命令:su -username,或者使用su -l username執(zhí)行的登錄切換。
非交互式登錄shell進(jìn)程:
su username執(zhí)行的登錄切換;
圖形界面下打開的終端
profile類:
全局:對所有用戶都生效:
/etc/profile
/etc/profid.d/*.sh
用戶個人:僅對當(dāng)前用戶有效;
~/.bash_profile
功用:
1、用戶定義環(huán)境變量
2、運行命令或腳本
bashrc類:
全局:
/etc/bashrc
用戶個人:
~/.bashrc
功用:
1、定義本地變量:
2、定義命令別名:
注意:僅管理員可修改全局配置文件
交互式登錄shell進(jìn)程:
/etc/profile-->/etc/profile.d/*-->/.bash_profile-->~/.bashrc-->/etc/bashrc
非交互式登錄shell進(jìn)程:
~/.bashrc-->/etc/bashrc-->/etc/profile.d/*
命令行中定義的特性,例如變量和別名作用域為當(dāng)前shell進(jìn)程的生命周期
配置文件定義的特性,只對隨后新啟動的shell進(jìn)程有效;
讓通過配置文件定義的特性立即生效:
(1)通過命令行中重復(fù)定義一次;
(2)讓shell進(jìn)程重讀配置文件;
source /path/from/conf_file
. /path/from/conf_file
問題1:定義對所有用戶都生效的命令別名,例如“l(fā)ftps=lftp 172.16.1.110/pub”?
問題2:讓centos用戶登錄時,提示其已經(jīng)登錄,并提示當(dāng)前時間。
vim /etc/profile.d//welcome.sh
echo "Welcome login!"
echo -n "NOW Time is: "
date
echo -n "Login ip:"
who | awk 'END{print $5}' |tr "()" " "
bash的算術(shù)運算
+ ,- ,*,/ ,** ,%
取模,取余%
3%2=1
100%55=45
算術(shù)運算格式
(1)let VAR=算術(shù)運算表達(dá)式
(2)VAR=$[算術(shù)運算表達(dá)式]
(3)VAR=$((算術(shù)運行表達(dá)式))
(4)VAR=$(expr $ARG1 $OP $ARG2)
注意:乘法符號在有些場景中需要使用轉(zhuǎn)義符
練習(xí):寫一個腳本,完成如下功能;添加三個用戶;求此三個用戶的UID之和
#i/usr/bash
for((i=1;i<=3;i++));do
username="user$i"
useradd "$username"
echo "$username" | passwd --stdin $username
num=$(id -u "$username")
let sum=sum+$num
done
echo $sum
條件判斷
bash中如何實現(xiàn)條件判斷?
條件測試類型
整數(shù)測試
字符測試
文件測試
條件測試的表達(dá)式
[ expression ]
[[ expression ]]
test expression
整數(shù)比較:
-eq:測試兩個整數(shù)是否相等:比如$a -eq $b
-ne:測試兩個整數(shù)是否不等:不等,為真:相等,為假
-gt:測試一個數(shù)是否大于另一個數(shù):大于,為真;否則,為假
-lt:測試一個數(shù)是否小于另一個數(shù):小于,為真;否則,為假
-ge:大于或等于
-le:小于或等于
練習(xí):
1.判斷當(dāng)前系統(tǒng)上是否有用戶的默認(rèn)shell為bash;如果有,就顯示有多少個這類用戶;否則,就顯示沒有這類用戶
2.判定命令歷史中歷史命令的總條目是否大于1000;如果大于就顯示“some command will gone”;否則顯示“OK”
num=`history | tail -1 | awk '{print $1}'`
if [[ $num -gt 1000 ]];then
echo "OK!"
else
echo "Some command will gone"
fi
3.給定一個用戶,獲取其mime警告期限;而判斷用戶mime使用期限是否已經(jīng)小于警告期限(提示:計算方法,最長使用期限減去已經(jīng)使用的天數(shù)即為剩余使用期限);如果小于,則顯示“warning”;否則,就顯示“OK”
#!/bin/bash
TODAY=`date +%s`
ZUIJIN=`tail -1 /etc/shadow | cut -d":" -f3`
SHIY ))
ZUICHANG=`tail -1 /etc/shadow | cut -d":" -f5`
JINGAO=`tail -1 /etc/shadow | cut -d":" -f6`
SY=$[ $ZUICHANG-$SHIYONG ]
if [ $SY -gt $JINGAO ];then
echo "OK!"
else
echo "Warning!"
fi
文件測試:
-e FILE:測試文件是否存在 存在為true
-f FILE:測試文件是否為普通文件
-d FILE:測試指定路徑是否為目錄
-r FILE:測試當(dāng)前用戶對指定文件是否有讀權(quán)限
-w FILE:
-x FILE:
[ -x /etc/rc.d/rc.sysinit ]
字符串測試:
== 測試是否相等,等為真,不等為假
!=:測試是否不等,不等為真,等為假
>
<
-z sting:測試指定字符串是否為0,0為真,不為0則假
-n string: 測試指定字符串是否為0,不為0為真,0則假
-str string:測試指定字符串是否不空,不空為真,空則假
if []
組合測試:
-a:與關(guān)系
-o:或關(guān)系
?。悍顷P(guān)系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
測試腳本是否有語法錯誤:
bash -n
單步執(zhí)行:
bash -x
練習(xí)
1.給定一個文件,如果是一個普通文件,就顯示之;如果是一個目錄,亦顯示之;否則,此為無法識別之文件。
#!/bin/bash
FILE=/etc/shadow2
if [ ! -e $FILE ];then
echo "NO such file."
exit 1
fi
if [ -e $FILE ];then
echo "wenjian"
elif [ -d $FILE ];then
echo "mulu"
else
echo "Unknown"
fi
2.給腳本傳遞兩個參數(shù)(整數(shù));顯示此兩者之和,之積。
#/bin/bash
if [ $# -ne 2 ]; then
echo "Plese Enter Two AGE"
exit 2
fi
HE=$[ $1+$2 ]
JI=$[ $1*$2 ]
echo "$1 + $2=$HE"
echo "$1 * $2=$JI"練習(xí):
1、傳遞一個用戶名參數(shù)腳本,判斷此用戶的用戶名跟其基本組的組名是否一致,并將結(jié)果顯示出來
#!/bin/bash
if ! id $1 &>/dev/null;then
echo "NO such User"
exit 6
fi
G=`id -n -g $1`
if [ $G = $1 ];then
echo "yiyang"
else
echo " buyiyang"
fi
2、傳遞三個參數(shù)給腳本,第一個為整數(shù),第二個為算術(shù)運算符,第三個為整數(shù),將計算結(jié)果顯示出來,要求保留兩位精度。如: ./calc.sh 5 / 2
#!/bin/bash
echo "scale=2;$1$2$3 "|bc
3、傳遞三個參數(shù)給腳本,參數(shù)均為用戶名。將此用戶的賬號信息提取出來后放置于/tmp/testusers.txt文件中,并要求每一行行首有行號。
#!/bin/bash
for i in $@;do
if ! id $i &>/dev/null;then
echo "$i Not User"
exit 6
fi
done
echo "1 $1" | tee -a /tmp/testuser.txt
echo "2 $2" | tee -a /tmp/testuser.txt
echo "3 $3" | tee -a /tmp/testuser.txt
#!/bin/bash
for i in $@;do
if ! id $i &>/dev/null;then
echo "$i Not User"
exit 6
fi
done
m=1
while (( $m<=$# ));do
for i in $@;do
echo $m $i |tee -a /tmp/testusers.txt
let "m++"
done
done
4、寫一個腳本:
判斷當(dāng)前主機(jī)的CPU生產(chǎn)商,其信息在/proc/cpuinfo文件中vendor id 一行中。
如果其生產(chǎn)商為AuthenticAMD,就顯示為AMD公司
如果其生產(chǎn)商為GenuineIntel,就顯示為Intel公司
否則,就說其為非主流公司#!/bin/bash
CPU=`grep "vendor_id" /proc/cpuinfo | head -1 | awk '{print $3}'`
if [ $CPU == "AuthenticAMD" ];then
echo "AMD"
elif [ $CPU == "GenuineIntel" ]
echo "Intel"
else
echo "Feizhuliu"
fi
5、寫一個腳本:
給腳本傳遞三個參數(shù),判斷其中 的最大數(shù)和最小數(shù),并顯示出來
#!/bin/bash
MAX=0
for i in $@;do
if [ $i -gt $MAX ];then
MAX=$i
fi
done
echo Max is $MAX
SMALL=0
NUM=0
for i in $@;do
let NUM++
[ $NUM -eq 1 ]&& SMALL=$i
if [ $i -lt $SMALL ];then
SMALL=$i
fi
done
echo Small is $SMALL
條件判斷,控制結(jié)構(gòu):
單分支if語句
if 判斷條件;then
statement1
statement1
...
fi
雙分支的if語句:
if 判斷條件;then
statement1
statement2
...
else
statement3
statement4
...
fi
多分支if語句:
if 判斷條件;then
statement1
statement2
elif 判斷條件2;then
statement3
statement4
elif 判斷條件3;then
statement5
statement6else
statement7
fi
case語句
case SWITCH in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
寫一個腳本:
只接收參數(shù)start,stop,restrart,status其中之一。
#!/bin/bash
case $1 in
'start')
echo "start!";;
'stop')
echo "stop!";;
'restart')
echo "restart!";;
'staus')
echo "staus!";;
*)
echo `basename $0` "(start|stop|restrart|status)"
esac
寫一個腳本,可以接受選項及參數(shù),而后能獲取每一個選項,及選項的參數(shù);并能根據(jù)選項參數(shù)做出特定的操作,比如:
adminusers.sh --add tom,jerry --del tom,blair -v|--verbose -h|--help
#!/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
USERS=$2
shift 2 ;;
--del)
DEL=1
USERS=$2
shift 2 ;;
*)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 6 ;;
esac
fi
done
if [ $ADD -eq 1 ];then
for user in `echo $USERS | tr "," " "`;do
if id $user &>/dev/null;then
[ $DEBUG -eq 1 ] && echo "$user exists"
else
useradd $user
echo $user | passwd --stdin $user &>/dev/null
[ $DEBUG -eq 1 ] && echo "Add user:$user finished! "
fi
done
fi
if [ $DEL -eq 1 ];then
for user in `echo $USERS | tr "," " "`;do
if id $user &>/dev/null;then
userdel -rf $user &>/dev/null
[ $DEBUG -eq 1 ] && echo "$user Delete finished!"
else
[ $DEBUG -eq 1 ] && echo "$user Not exist. "
fi
done
fi
練習(xí):寫一個腳本showlogged.sh,其中語法格式為:
showlogged.sh -v -c -h|--help
其中,-h選項只能單獨使用,用于顯示幫助信息;-c選項時,顯示當(dāng)前系統(tǒng)上登錄的所有用戶數(shù);如果同時使用了-v選項,則即顯示同時登錄的用戶數(shù),又顯示登錄的用戶的相關(guān)信息;如:
logged users: 4
they are:
root pts/0 2016-10-09 12:38 (171.221.140.180)
root pts/2 2016-10-09 13:15 (171.221.140.180)
root pts/3 2016-10-09 13:16 (171.221.140.180)
#!/bin/bash
declare -i DEBUG=0
declare -i USER=0
for i in `seq 1 $#`;do
if [ $# -gt 0 ];then
case $1 in
-v)
DEBUG=1
shift;;
-h|--help)
echo "Usage:`basename $0` -v -c -h|--help"
exit 0;;
-c)
USER=1
shift ;;
*)
echo "Usage:`basename $0` -v -c -h|--help"
exit 7;;
esac
fi
done
if [ $USER -eq 1 ];then
num=`who | wc -l`
echo "Logged users:$num"
if [ $DEBUG -eq 1 ];then
echo "They are:"
who
fi
fi
循環(huán):進(jìn)入條件,退出條件
for循環(huán)格式:
for varaible in list ;do
循環(huán)體
done
for ((expr1;expr2;expr3));do
循環(huán)體
done
如何生成列表:
{1..100}
`seq [起始數(shù) [步進(jìn)長度] ] 結(jié)束數(shù)`
聲明變量 declare -i sum=0
integer
-x 環(huán)境變量
#!/bin/bash
sum=0
for i in {1..100};do
let sum=$sum+$i
done
echo $sum
練習(xí):寫一個腳本
(1、設(shè)定變量FILE的值為/etc/passwd
(2、依次向/etc/passwd中的每個用戶問好,并顯示對方的shell,如:Hello, root ,your shell: /bin/bash
(3、統(tǒng)計一共有多少個用戶
#!/bin/bash
LIST=`awk -F: '{print $1}' /etc/passwd`
for i in $LIST;do
BS=`grep "^$i\>" /etc/passwd | awk -F: '{print $7}'`
echo "Hello,$i Your bash is $BS"
done
sum=`wc -l /etc/passwd | cut -d' ' -f1`
echo "$sum /etc/passwd users"
2、寫一個腳本
添加10個用戶user1到user10,但要求只有用戶不存在的情況下才添加
#!/bin/bash
for m in {1..10};do
i=user$m
! id $i &> /dev/null && useradd $i && echo $i | passwd --stdin $i &> /dev/null || echo "$i is exists"
done
擴(kuò)展:
接收一個參數(shù):
add:添加user1-user10
del:刪除user1-user10
其他:退出
#!/bin/bash
if [[ $1 != add && $1 != del ]];then
echo "Plese ENter add OR del"
echo "exit..."
exit 6
fi
for i in {1..10};do
NAME=user$i
if [[ $1 == add ]];then
useradd $NAME &>/dev/null && echo $NAME | passwd --stdin $NAME&>/dev/null && echo "$NAME add OK!" || echo "$NAME is Exists"
elif [[ $1 == del ]];then
userdel -rf $NAME &>/dev/null&& echo "$NAME delete OK!" || echo "$NAME no Such"
else
echo "ARG Error!"
fi
done
3、寫一個腳本:
計算100以內(nèi)所有能被3整除的正整數(shù)的和
#!/bin/bash
declare -i sum=0
for i in {1..100};do
if (($i%3==0));then
let sum=$[$sum+$i]
fi
done
echo $sum
4、寫一個腳本:
計算100以內(nèi)所有奇數(shù)的和以及所有偶數(shù)的和
#!/bin/bash
for i in {1..100};do
if (($i%2==0));then
let sum=$sum+$i
fi
done
echo $sum
#!/bin/bash
for i in {1..100};do
if (($i%2==1));then
let sum=$sum+$i
fi
done
echo $sum5、寫一個腳本,分別顯示當(dāng)前系統(tǒng)上所有默認(rèn)shell為bash的用戶和默認(rèn)shell為/sbin/nologin的用戶,并統(tǒng)計各類shell下的用戶總數(shù)。顯示結(jié)果如:
bash,3users,they are: root,redhat,gentoo
nologin,2users ,they are: bin ftp
#!/bin/bash
BASH_array=(`grep "\<bash\>$" /etc/passwd | cut -d":" -f1`)
BASH_num=`grep -c "\<bash\>$" /etc/passwd`
NOLOGIN_array=(`grep "\<nologin\>$" /etc/passwd | cut -d":" -f1`)
NOlOGIN_num=`grep -c "\<nologin\>$" /etc/passwd`
echo "bash,${BASH_num} users, they are:${BASH_array[@]}"
echo "nologin,${NOlOGIN_num} users, they are:${NOLOGIN_array[@]}"
while循環(huán):
適用于循環(huán)次數(shù)未知的場景,要有條件退出
while CONDITION;do
循環(huán)體
循環(huán)控制變量修正表達(dá)式
done
進(jìn)入條件:CONDITION測試為“真”
退出條件:CONDITION測試為“假”
while的特殊用法一:
while : ;do
done
while的特殊用法二:
while read LINE;do
done < /PATH/TO/SOMEFILE
練習(xí):計算100以內(nèi)所有正整數(shù)的和。
#!/bin/bash
declare -i i=1
declare -i num=0
while [ $i -le 100 ];do
let sum=$sum+$i
let i++
done
echo $sum
寫一個腳本
1.顯示一個菜單給用戶:
d|D) show disk usages.
m|M) show memory usages
s|S) show swap usages
*) quit
2.當(dā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"Please Choice:" CHOICE
while [ $CHOICE != 'quit' ];do
case $CHOICE in
d|D)
echo -e "\033[32mdisk usage: \033[0m"
df -Ph;;
m|M)
echo -e "\033[33mMemory usage: \033[0m"
free -m |grep "Mem";;
s|S)
echo -e "\033[34mSwap usage: \033[0m"
free -m |grep "Swap";;
*)
echo -e "\033[31mUnknown! \033[0m"
esac
read -p"Please Choice:" CHOICE
done
until循環(huán):
until CONDITION;do循環(huán)體
循環(huán)控制變量修正表達(dá)式done
進(jìn)入條件:CONDITION測試為“假”
退出條件:CONDITION測試為“真”
exit:退出循環(huán)
如果腳本沒有明確定義退出狀態(tài)碼,那么最后執(zhí)行的一條命令的退出碼即為腳本的退出狀態(tài)碼
break:提前退出循環(huán)
continue:提前結(jié)束本輪循環(huán),而進(jìn)入下一輪循環(huán)
示例:求100以內(nèi)正整數(shù)的和
練習(xí):分別使用for,while,until實現(xiàn)
1、分別求100以內(nèi)所有偶數(shù)之和,100以內(nèi)所有奇數(shù)之和;
#!/bin/bash
for m in {1..100}
do
if(($m%2==0));then
let num=$num+$m
fi
done
echo $num
#!/bin/bash
for m in {1..100}
do
if(($m%2==1));then
let num=$num+$m
fi
done
echo $num
2、創(chuàng)建10個用戶,user101-user110;密碼同用戶名
#!/bin/bash
for m in {101..110};do
i=user$m
! id $i &> /dev/null && useradd $i && echo $i | passwd --stdin $i &> /dev/null || echo "$i is exists"
done
3、打印99乘法表;
#!/bin/bash
for m in {1..9}
do
for((n=1;n<=m;n++))
do
echo -n "$n*$m = $(($m*$n)) "
done
echo -e "\n"
done
4、打印逆序的九九乘法表
#!/bin/bash
for m in {9..1}
do
for((n=1;n<=m;n++))
do
echo -n "$n*$m = $(($m*$n)) "
done
echo -e "\n"
done
5、寫一個腳本,利用RANDOM生成10個隨機(jī)數(shù),并找出其中最大值,和最小值。
#!/bin/bash
#
declare -i max=0
declare -i min=0
for i in {1..10};do
rand=$RANDOM
[ $i -eq 1 ] && min=$rand
if [ $i -le 9 ];then
echo -n "$rand,"
else
echo $rand
fi
[ $rand -gt $max ] && max=$rand
[ $rand -lt $min ] && min=$rand
done
echo "MAX:$max"
echo "MIN:$min"寫一個腳本:
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)實現(xiàn)。
#!/bin/bash
declare -i LAST=150
while [ $LAST -le 254starry ];do
#until [ $LAST -gt 254 ];do
IP=222.73.22.$LAST
if ping -c 1 -W 1 $IP &> /dev/null;then
echo -e "IP:\033[32m $IP \033[0m is up"
else
echo -e "IP:\033[31m $IP \033[0m is down"
fi
let LAST++
done
#!/bin/bash
for i in {150..254};do
#for ((i=150;i<=254;i++));do
IP=222.73.22.$i
if ping -c 1 -W 1 $IP &> /dev/null;then
echo -e "IP:\033[32m $IP \033[0m is up"
else
echo -e "IP:\033[31m $IP \033[0m is down"
fi
done寫一個腳本(前提:請為虛擬機(jī)新增一塊硬盤,架設(shè)它為/dev/sdb),為指定的硬盤創(chuàng)建分區(qū),
1)列出當(dāng)前系統(tǒng)上所有的磁盤,讓用戶選擇,如果選擇quit則退出腳本;如果用戶選擇錯誤,就讓用戶重新選擇
2)當(dāng)用戶選擇后,提醒用戶確認(rèn)接下來的操作可能會損壞數(shù)據(jù),并請用戶確認(rèn),如果用戶選擇y就繼續(xù),n就退出,否則,讓用戶重新選擇
3)抹除那塊硬盤上的所有分區(qū)(提示:抹除所有分區(qū)后執(zhí)行sync命令,并讓腳本睡眠3秒種后再分區(qū));并為其創(chuàng)建三個主分區(qū),第一個為20M,第二個為512M,第三個為128M,且第三個為swap分區(qū)類型:(提示:將分區(qū)命令通過echo傳送給fdisk即可實現(xiàn))
#!/bin/bash
echo "Initial a Disk..."
echo -e "\033[31mWarning:Data will be lost!!!\033[0m"
fdisk -l | grep "Disk /dev/[vhs]d[a-z]" | awk -F: '{split($1,D," ");printf"Disk%d:%s\n",NR,D[2]}'
echo -en "\033[31mYour Choice:\033[0m"
read dk
if [ $dk == 'quit' ];then
echo "Exiting..."
exit 5
fi
until fdisk -l | grep "Disk /dev/[vhs]d[a-z]" | awk -F: '{print $1}' | grep "Disk $dk$" &>/dev/null ;do
echo -en "\033[31mChoose wrong, please choose again:\033[0m"
read dk
if [ $dk == 'quit' ];then
echo "Exiting..."
exit 5
fi
done
echo -en "\033[31mClear all data,Please Choice y or n:\033[0m"
read choice
until [ $choice == 'y' -o $choice == 'n' ];do
echo -en "\033[31mChoose wrong, please choose y or n:\033[0m"
read choice
done
if [ $choice == 'n' ];then
echo "Quiting..."
exit 6
else
for i in `df -lh | grep "/dev/sdc" | awk '{print $1}'`;do
fuser -km $i
umount $i &>/dev/null
echo -e "\033[31m$i umount finish!\033[0m"
done
dd if=/dev/zero of=$dk bs=512 count=1 &>/dev/null
sync
sleep 3
echo "
n
p
1
+20M
n
p
2
+512M
n
p
3
+128M
t
3
82
w" | fdisk $dk &>/dev/null
partprobe $dk &>/dev/null
sync
sleep 2
mke2fs -j ${dk}1 &>/dev/null
echo -e "\033[32m${dk}1 formatting finish!\033[0m"
mke2fs -j ${dk}2 &>/dev/null
echo -e "\033[32m${dk}2 formatting finish!\033[0m"
mkswap ${dk}3 &>/dev/null
echo -e "\033[32m${dk}3 formatting finish!\033[0m"
fi
fdisk -l $dk
swapon ${dk}3
寫一個腳本,完成以下功能:(說明:此腳本能于同一個repo文件中創(chuàng)建多個yum源的指向)
①接受一個文件名做為參數(shù),此文件存放至/etc/yum.repos.d目錄中,且文件名以.repo為后綴
②在腳本中,提醒用戶輸入repo id ;如果為quit,則退出腳本;否則,繼續(xù)完成下面的步驟:
③repo name以及baseurl的路徑,而后以repo文件的格式將其保存至指定的文件中;
④enabled默認(rèn)為1,而gpgcheck默認(rèn)設(shè)定為0
⑤此腳本會循環(huán)執(zhí)行多次,除非用戶為repo id指定為quit
#!/bin/bash
REPO=/etc/yum.repos.d/$1
if [ -e $REPO ];then
echo "The $1 Exist!"
exit 3
fi
echo -en "\033[32mPlease Enter Repo Id:\033[0m"
read REPOID
until [ $REPOID == "quit" ];do
echo "[$REPOID]" >> $REPO
echo -en "\033[34mPlease Enter Repo Name:\033[0m"
read REPONAME
echo "name=$REPONAME" >> $REPO
echo -en "\033[34mPlease Enter baseurl:\033[0m"
read BASEURL
echo "baseurl=$BASEURL" >> $REPO
echo -e "enabled=1\ngpgcheck=0" >>$REPO
echo -en "\033[32mPlease Enter Repo Id:\033[0m"
read REPOID
done
echo "quit..."
exit 0
寫一個腳本,完成如下功能:(說明:此腳本能夠為指定網(wǎng)卡創(chuàng)建別名,則指定地址;使用格式如;mkethalias.sh -v|--verbose -i ethx)
①-i 選項用于指定網(wǎng)卡;指定完成以后,要判斷其是否存在,如果不存在,就退出
②如果用戶知道的網(wǎng)卡存在,則讓用戶為其指定一個別名,此別名可以為空,如果不空,請確保其事先不存在,否則,要報錯,并讓用戶重新輸入
③在用戶輸入了一個正確的別名后,請用戶輸入地址和掩碼;并將其配置在知道的別名上;
④如果用戶使用了-v選選,則在配置完成后,顯示其配置結(jié)果信息:否則,將顯示
寫一個腳本:
①判斷一個值得的bash腳本是否有語法錯誤:如果有錯誤,則提醒用戶鍵入Q或者q無視錯誤并退出,其他任何鍵可以通過vim打開這個值得的腳本
②如果用戶通過vim打開編輯后保存并退出時任然有錯誤,則重復(fù)第一步中的內(nèi)容:否則,就正常關(guān)閉退出
#!/bin/bash
until `bash -n $1 &>/dev/null`;do
echo -ne "\033[31mSyntax error ,[Q|q] to quit bash; others for vim $1: \033[0m"
read INPUT
if [ $INPUT != "q" -a $INPUT != "Q" ];then
vim $1
continue
else
echo "quit...!"
exit 5
fi
done
echo "$1 bash is OK!"#!/bin/bash
until `bash -n $1 &>/dev/null`;do
echo -ne "\033[31mSyntax error ,[Q|q] to quit bash; others for vim $1: \033[0m"
read CHOSE
case $CHOSE in
Q|q)
echo "Syntax error ,quit!"
exit 3;;
*)
vim $1;;
esac
done
echo "$1 bash is OK!"
函數(shù)
function:功能
結(jié)構(gòu)化編程,不能獨立運行,需要調(diào)用時執(zhí)行,可以被多次調(diào)用
定義一個函數(shù):
function FUNCNAME{
command
}
FUNCNAME(){
command
}
自定義執(zhí)行狀態(tài)返回值:
return #
0-255
寫一個腳本,判定192.168.0.200-192.168.0.254之間的主機(jī)哪些在線。要求:
①使用函數(shù)來實現(xiàn)一臺主機(jī)的判斷過程
②在主程序中來調(diào)用此函數(shù)判定指定范圍內(nèi)的所有主機(jī)的在線情況
#!/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
IP=192.168.0.$i
PING $IP
if [ $? -eq 0 ];then
echo -e "IP:\033[32m $IP \033[0m is up"
else
echo -e "IP:\033[31m $IP \033[0m is down"fi
done
寫一個腳本:使用函數(shù)完成
①函數(shù)能夠接受一個參數(shù),參數(shù)為用戶名;判斷一個用戶存在,如果存在就返回此用戶的shell和UID;并返回正常狀態(tài)值;如果不存在就說此用戶不存在,并返回錯誤狀態(tài)值
②在主程序中調(diào)用函數(shù)
擴(kuò)展①:在主程序中,讓用戶自己輸入用戶名后,傳遞函數(shù)來進(jìn)行判斷;
擴(kuò)展②:在主程序中,輸入用戶名判斷后不退出腳本,而是提示用戶繼續(xù)輸入下一個用戶名;如果用戶輸入的用戶不存在,請用戶重新輸入,但如果用戶輸入的是q或Q就退出。
#!/bin/bash
USERID(){
if id $1&>/dev/null;then
return 0
else
return 1
fi
}
echo -ne "\033[32mPlease input UserName:\033[0m"
read USERNAME
while :;do
USERID $USERNAME
RETU=$?
if [ $USERNAME == "Q" -o $USERNAME == "q" ];then
echo -e "\033[35mquit...\033[0m"
exit 6
elif [ $RETU -eq 1 ];then
echo -ne "\033[31mUsers not exits!Please agin input:\033[0m"
read USERNAME
continue
else
cat /etc/passwd | grep "$USERNAME" | awk -F: '{printf "%s Uid:%d shell:%s\n",$1,$3,$NF}'
fi
echo -ne "\033[32mPlease input UserName:\033[0m"
read USERNAME
done
${parameter#*/word}
${parameter##*/word}
FILE=/usr/local/src
${FILE#*/}: usr/local/src
${FILE##*/}: src
${parameter%/*word}
${parameter%%/*word}
${FILE%/*}: /usr/local
${FILE%%/*}:
服務(wù)樣例腳本:
#!/bin/bash
#
# chkconfig:2345 45 55
# description:This is my services!
FILE=/var/lock/subsys/mylinux
NAME=`basename $0`
STATUS(){
if [ -e $FILE ];then
echo -e "\033[32m$NAME is running... \033[0m"
else
echo -e "\033[31m$NAME is stoped\033[0m"
fi
}
USAGE(){
echo "/etc/init.d/$NAME {start|stop|restart|status}"
}
case $1 in
start)
echo "starting..."
touch $FILE;;
stop)
echo "stoping..."
rm -f $FILE &>/dev/null;;
restart)
echo "restarting...";;
status)
STATUS ;;
*)
USAGE;;
esac復(fù)制命令以及命令依賴的庫文件到新的根目錄
#!/bin/bash
MYROOT=/www/myroot
cplib(){
libdir=${1%/*}
newlib=$MYROOT$libdir
[ ! -d $newlib ] && mkdir -p $newlib
[ ! -e $MYROOT$1 ] && cp $1 $newlib && echo -e "\033[35m$1 copy finished!\033[0m"
}
cpcmd(){
cmddir=${1%/*}
newcmd=$MYROOT$cmddir
[ ! -d $newcmd ] && mkdir -p $newcmd
[ ! -e $MYROOT$1 ] && cp $1 $newcmd
for i in `ldd $1 | grep -o "/.*lib\(64\)\?/[^[:space:]]\+"`;do
cplib $i
done
}
echo -ne "\033[34mPlease input Command:\033[0m"
read CMD
until [ $CMD == 'q' ];do
! which $CMD &>/dev/null && echo -ne "\033[31mCommand not exist,Please againe input:\033[0m" && read CMD && continue
COMMAND=`which $CMD | grep -v "alias" | grep -o "[^[:space:]]\+"`
cpcmd $COMMAND
echo -e "\033[32m$COMMAND copy finished!\033[0m"
echo -ne "\033[33mPlease input Command:\033[0m"
read CMD
done變量中的字符長度:${#var}
系統(tǒng)函數(shù)庫樣本:
SCREEN=`stty -F /dev/console size 2>/dev/null`
COLUMNS=${SCREEN#* }
[ -z $COLUMNS ]&& COLUMNS=80
SPA_COL=$[$COLUMNS-14]
RED='\033[1;31m'
GREEN='\033[1;32m'
BLUE='\033[1;34m'
NORMAL='\033[0m'
success(){
string=$1
RT_SPA=$[$SPA_COL-${#string}]
echo -n $string
for i in `seq 1 $RT_SPA`;do
echo -n " "
done
echo -e "[ ${GREEN}OK${NORMAL} ]"
}
failde(){
string=$1
RT_SPA=$[$SPA_COL-${#string}]
echo -n $string
for i in `seq 1 $RT_SPA`;do
echo -n " "
done
echo -e "[ ${RED}FAILED${NORMAL} ]"
}
變量賦值:
${parameter:-word}:如果parameter為空或未定義,則變量展開為“word”;否則,展開為parameter的值
${parameter:+word}:如果parameter為空或未定義,不做任何操作”;否則,展開為“word”的值
${parameter:=word}:如果parameter為空或未定義,則變量展開為“word”;并將展開后的值賦值給parameter
${parameter:offset}
${parameter:offset:length}:取子串,從offset處的后一個字符開始,取lenth長的子串
腳本配置文件:
/etc/rc.d/init.d服務(wù)腳本
服務(wù)腳本支持配置文件:/etc/sysconfig/服務(wù)腳本同名的配置文件
局部變量:
local VAR_NAME=
a=1
test (){
local a=$[3+4]
}
test
for i in 'seq $i 10';do
echo $i
done
mktemp命令:
mktemp - create a temporary file or directory
mktemp [OPTION]... [TEMPLATE]常用選項:
-d :創(chuàng)建臨時目錄
注意:mktemp會將創(chuàng)建的臨時文件名直接返回,因此,可以直接通過命令引用保存起來
信號:
kill -SIGNAL PID
1:HUP
2:INT(Ctrl+c)
9:KILL
15:TERM
腳本中,能實現(xiàn)信號捕捉,但9和1無法捕捉
trap命令:信號捕捉
trap 'COMMAND' 信號類別
trap 'echo "no quit"' INT Ctrl+c的時候輸出 no quit
一個執(zhí)行多個語句,語句間用分號分隔
#!/bin/bash
TRAP(){
rm -rf /var/tmp/test
echo "quit and cleaning"
}
trap 'TRAP;exit 5' INT
mkdir -p /var/tmp/test
while true;do
file=/var/tmp/test/file-`date +%H%M%S`
touch $file
echo "Touch $file ok!"
sleep 2
done
數(shù)組
如何聲明一個數(shù)組:
declare -a AA
賦值方法1:
AA[0]=jerry
AA[1]=tom
AA[2]=wendy
AA[6]=natasha
賦值方法2:
AA=(jerry tom wendy natasha)
AA=([0]=jerry [1]=tom [2]=wendy [6]=natasha)
AA[3] =selina
AA[4] =nikita
${#AA[0]}:第一個元素的長度${#AA[1]}第二個元素個數(shù)的長度
${#AA[*]}: 元素個數(shù)
${#AA[@]}:元素個數(shù)
${AA[*]}: 所有元素
${AA[@]}:所有元素練習(xí):
1、數(shù)組的元素個數(shù)為1-39
2、數(shù)組元素不能相同
3、顯示此數(shù)組各元素的值
#!/bin/bash
read -p "input numbers[1-39]:" NUM
declare -a ARRAY
BJ(){
for j in `seq 0 $[${#ARRAY[@]}-1]`;do
if [ $1 -eq ${ARRAY[$j]} ];then
return 1
fi
done
return 0
}
for i in `seq 0 $[$NUM-1]`;do
while true;do
RAND=$[$RANDOM%40]
BJ $RAND
if [ $? -eq 0 ];then
break
fi
done
ARRAY[$i]=$RAND
echo "${ARRAY[$i]}"
done
getopts命令:獲取選項
$OPTARG 獲取選項參數(shù)
$OPTIND 選項和參數(shù)的數(shù)量
bash腳本使用選項
#!/bin/bash
while getopts ":d:" SWITCH;do
case $SWITCH in
d)
DESC=$OPTARG;;
\?)
echo "Usage:`basename $0` [-d descriprion] FILENAME";;
esac
done
shift $[$OPTIND-1]
if ! grep "[^[:space:]]" $1 &> /dev/null;then
cat > $1 << EOF
#!/bin/bash
# Name:`basename $1`
# Description:$DESC
# Author:Tcj
# Version:0.0.1
# Datetime: `date "+%F %T"`
# Usage:`basename $1`
#
EOF
fi
vim + $1
until bash -n $1 &> /dev/null;do
echo -ne "\033[31mSyntax error ,[Q|q] to quit `basename $0`; others for vim $1: \033[0m"
read CHOSE
case $CHOSE in
Q|q)
echo "Syntax error ,quit!"
exit 3;;
*)
vim $1;;
esac
done
echo "$1 bash grammar is OK!"
chmod +x $1
練習(xí):寫一個腳本getinterface.sh,腳本可以接受選項(i,I,a),完成以下任務(wù)
1、使用以下形式:getinterface.sh [-i interface|-I IP|-a]
2、當(dāng)用戶使用-i選項時,顯示其指定網(wǎng)卡的IP地址
3、當(dāng)用戶使用-I選項時,顯示其后面的IP地址所屬的網(wǎng)絡(luò)接口
4、當(dāng)用戶單獨使用-a選項時,顯示所有網(wǎng)絡(luò)接口及其IP地址(除lo除外)
#!/bin/bash
# Name:getinterface.sh
# Description: Get ehternet information
# Author:Tcj
# Version:0.0.1
# Datetime: 2016-11-28 23:12:23
# Usage:getinterface.sh [-i INTERFACE|-I IP|-a ]
#
GETIP(){
if ! ifconfig | grep -o "^[^[:space:]]\+" | grep $1 &>/dev/null;then
echo "Wrong ehtercard!"
exit 5
fi
IP=`ifconfig $1 | grep -o "inet addr:[0-9\.]\+" | cut -d":" -f2`
}
GETNET(){
if ! ifconfig | grep -o "inet addr:[0-9\.]\+" | cut -d":" -f2 | grep $1 &>/dev/null;then
echo "Wrong IP!"
exit 6
fi
NETWORK=`ifconfig | grep -B 1 "inet addr:$1" | grep -o "^[^[:space:]]\+"`
}
GETALL(){
for i in `ifconfig | grep -o "^[^[:space:]]\+" | grep -v "lo"`;do
GETIP $i
echo "$i:$IP"
done
}
USAGE(){
echo "usage:`basename $0`[-i INTERFACE|-I IP|-a ]"
}
while getopts ":i:I:a" OPT;do
case $OPT in
i)
GETIP $OPTARG
echo -e "$OPTARG:\033[32;1m$IP\033[0m";;
I)
GETNET $OPTARG
echo -e "$OPTARG:\033[32;1m$NETWORK\033[0m";;
a)
GETALL;;
\?)
USAGE;;
esac
done
2016年12月15日 上午11:24 沙發(fā)
挺好的,祝你快樂
2016年12月20日 下午3:54 板凳
偶然來訪,受益良多!
2016年12月24日 下午4:00 地板
掐指一算,這個博客能風(fēng)光一百年!