溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Shell企業(yè)編程基礎(chǔ)實戰(zhàn)

發(fā)布時間:2020-07-09 15:47:29 來源:網(wǎng)絡(luò) 閱讀:568 作者:PassZhang666 欄目:開發(fā)技術(shù)

Shell企業(yè)編程基礎(chǔ)

說到Shell編程,很多從事Linux運(yùn)維工作的朋友都不陌生,都對Shell有基本的了解,讀者可能剛開始接觸Shell的時候,有各種想法,感覺編程非常困難,SHELL編程是所有編程語言中最容易上手,最容易學(xué)習(xí)的編程腳本語言。

本章向讀者介紹Shell編程入門、Shell編程變量、If、While、For、Case、Select基本語句案例演練及Shell編程四劍客Find、Grep、Awk、Sed深度剖析等。

SHELL編程入門簡介

曾經(jīng)有人說過,學(xué)習(xí)Linux不知道Shell編程,那就是不懂Linux,現(xiàn)在細(xì)細(xì)品味確實是這樣。Shell是操作系統(tǒng)的最外層,Shell可以合并編程語言以控制進(jìn)程和文件,以及啟動和控制其它程序。

Shell 通過提示您輸入,向操作系統(tǒng)解釋該輸入,然后處理來自操作系統(tǒng)的任何結(jié)果輸出,簡單來說Shell就是一個用戶跟操作系統(tǒng)之間的一個命令解釋器。

Shell是用戶與Linux操作系統(tǒng)之間溝通的橋梁,用戶可以輸入命令執(zhí)行,又可以利用 Shell腳本編程去運(yùn)行,如圖所示:

Shell企業(yè)編程基礎(chǔ)實戰(zhàn)

Shell、用戶及Kernel位置關(guān)系

Shell企業(yè)編程基礎(chǔ)實戰(zhàn)

Linux Shell種類非常多,常見的SHELL如下:

  • Bourne Shell(/usr/bin/sh或/bin/sh)

  • Bourne Again Shell(/bin/bash)

  • C Shell(/usr/bin/csh)

  • K Shell(/usr/bin/ksh)

  • Shell for Root(/sbin/sh)

不同的Shell語言的語法有所不同,一般不能交換使用,最常用的shell是Bash,也就是Bourne Again Shell。Bash由于易用和免費(fèi),在日常工作中被廣泛使用,也是大多數(shù)Linux操作系統(tǒng)默認(rèn)的Shell環(huán)境。

Shell、Shell編程、Shell腳本、Shell命令之間都有什么區(qū)別呢?

簡單來說Shell是一個整體的概念,Shell編程與Shell腳本統(tǒng)稱為Shell編程,Shell命令是Shell編程底層具體的語句和實現(xiàn)方法。

SHELL腳本及Hello World

要熟練掌握Shell編程語言,需要大量的練習(xí),初學(xué)者可以用Shell打印“Hello World”字符,寓意著開始新的啟程!

Shell腳本編程需要如下幾個事項:

  1. Shell腳本名稱命名一般為英文、大寫、小寫;

  2. 不能使用特殊符號、空格來命名;

  3. Shell腳本后綴以.sh結(jié)尾;

  4. 不建議Shell命名為純數(shù)字,一般以腳本功能命名。

  5. Shell腳本內(nèi)容首行需以#!/bin/bash開頭;

  6. Shell腳本中變量名稱盡量使用大寫字母,字母間不能使用“-”,可以使用“_”;

  7. Shell腳本變量名稱不能以數(shù)字、特殊符號開頭。

如下為第一個Shell編程腳本,腳本名稱為:first_shell.sh,代碼內(nèi)容如下:

#!/bin/bash
#This is my First shell
#By author test.net
echo “Hello World ”

First_shell.sh腳本內(nèi)容詳解如下:

#!/bin/bash???????????? #固定格式,定義該腳本所使用的Shell類型;
#This is my First shell???? #號表示注釋,沒有任何的意義,SHELL不會解析它;
#By author test.net #表示腳本創(chuàng)建人,#號表示注解;
echo “Hello World !” #Shell腳本主命令,執(zhí)行該腳本呈現(xiàn)的內(nèi)容。

Shell腳本編寫完畢,如果運(yùn)行該腳本,運(yùn)行用戶需要有執(zhí)行權(quán)限,可以使用chmod o+x first_shell.sh賦予可執(zhí)行權(quán)限。然后./first_shell.sh執(zhí)行即可,還可以直接使用命令執(zhí)行: /bin/sh first_shell.sh直接運(yùn)行腳本,不需要執(zhí)行權(quán)限,最終腳本執(zhí)行顯示效果一樣。

初學(xué)者學(xué)習(xí)Shell編程,可以將在Shell終端運(yùn)行的各種命令依次寫入到腳本內(nèi)容中,可以把Shell腳本當(dāng)成是Shell命令的堆積。

Shell腳本字符串顏色

再介紹下字符串輸出顏色,有時候關(guān)鍵地方需要醒目,顏色是最好的方式:

字體顏色

  • 30:黑

  • 31:紅

  • 32:綠

  • 33:黃

  • 34:藍(lán)色

  • 35:紫色

  • 36:深綠

  • 37:白色

字體背景顏色

  • 40:黑

  • 41:深紅

  • 42:綠

  • 43:黃色

  • 44:藍(lán)色

  • 45:紫色

  • 46:深綠

  • 47:白色

顯示方式

  • 0:終端默認(rèn)設(shè)置

  • 1:高亮顯示

  • 4:下劃線

  • 5:閃爍

  • 7:反白顯示

  • 8:隱藏

格式:

\033[1;31;40m?? # 1 是顯示方式,可選。31 是字體顏色。40m 是字體背景顏色。
\033[0m???????????? # 恢復(fù)終端默認(rèn)顏色,即取消顏色設(shè)置。

示例:

#!/bin/bash
# 字體顏色
for i in {31..37}; do
echo -e "\033[$i;40mHello world!\033[0m"
done
# 背景顏色
for i in {41..47}; do
echo -e "\033[47;${i}mHello world!\033[0m"
done
# 顯示方式
for i in {1..8}; do
echo -e "\033[$i;31;40mHello world!\033[0m"
done

示例如圖:

測試單個案例

[root@localhost ~]# echo -e '\033[31;40mwww.test.net!\033[0m'
www.test.net!
Shell編程之變量詳解

Shell是非類型的解釋型語言,不像C++、JAVA語言編程時需要事先聲明變量,Shell給一個變量賦值,實際上就是定義了變量,在Linux支持的所有shell中,都可以用賦值符號(=)為變量賦值,Shell變量為弱類型,定義變量不需要聲明類型,但在使用時需要明確變量的類型,可以使用Declare指定類型。

Declare常見參數(shù)有:

+/-  "-"可用來指定變量的屬性,"+"為取消變量所設(shè)的屬性;
-f  僅顯示函數(shù);
r  將變量設(shè)置為只讀;
x  指定的變量會成為環(huán)境變量,可供shell以外的程序來使用;
i  指定類型為數(shù)值,字符串或運(yùn)算式。

Shell編程中變量分為三種,分別是系統(tǒng)變量、環(huán)境變量和用戶變量,Shell變量名在定義時,首個字符必須為字母(a-z,A-Z),不能以數(shù)字開頭,中間不能有空格,可以使用下劃線(_),不能使用(-),也不能使用標(biāo)點(diǎn)符號等。當(dāng)腳本中使用某個字符串較頻繁并且字符串長度很長時就應(yīng)該使用變量代替。

例如定義變量A=test.net,定義這樣一個變量,A為變量名,test.net是變量的值,變量名有格式規(guī)范,變量的值可以隨意指定。變量定義完成,如需要引用變量,可以使用$A。

如下腳本var.sh腳本內(nèi)容如下:

#!/bin/bash
#By author test.net
A=123
echo “Printf variables is $A.”

執(zhí)行該Shell腳本,結(jié)果將會顯示:Printf variables is 123。

Shell腳本中的變量其他使用還有很多例如:

  1. 使用條件語句時,常使用變量 if [ $i -gt 1 ]; then ... ; fi。

  2. 引用某個命令的結(jié)果時,用變量替代 n=wc -l test.txt。

  3. 寫和用戶交互的腳本時,變量也是必不可少的,read -p "Input a number: " i; echo $i 如果沒寫這個i,可以直接使用$REPLY。

  4. 內(nèi)置變量 $0, $1, $2… $0表示腳本本身,$1 第一個參數(shù),$2 第二個 .... $#表示參數(shù)個數(shù)。

  5. 數(shù)學(xué)運(yùn)算a=2;b=3; c=$(($a+$b))或者$[$a+$b]。

Shell編程之系統(tǒng)變量

Shell常見的變量之一系統(tǒng)變量,主要是用于對參數(shù)判斷和命令返回值判斷時使用,系統(tǒng)變量詳解如下:

$0         當(dāng)前腳本的名稱;
$n 當(dāng)前腳本的第n個參數(shù),n=1,2,…9;
$* 當(dāng)前腳本的所有參數(shù)(不包括程序本身);
$@???????????? 傳遞給腳本或函數(shù)的所有參數(shù)。被雙引號(" ")包含時,與 $* 稍有不同
$# 當(dāng)前腳本的參數(shù)個數(shù)(不包括程序本身);
$? 命令或程序執(zhí)行完后的狀態(tài),返回0表示執(zhí)行成功;
$$ 程序本身的PID號。

注意:

$* 和 $@ 的區(qū)別是什么?

$* 和 $@ 都表示傳遞給函數(shù)或腳本的所有參數(shù),不被雙引號(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數(shù)。

但是當(dāng)它們被雙引號(" ")包含時,"$*" 會將所有的參數(shù)作為一個整體(強(qiáng)調(diào)整體),以"$1 $2 … $n"的形式輸出所有參數(shù);即當(dāng)成一個整體輸出,每一個變量參數(shù)之間以空格隔開。

"$@" 會將各個參數(shù)分開(強(qiáng)調(diào)獨(dú)立),以"$1" "$2" … "$n" 的形式輸出所有參數(shù)。即每一個變量參數(shù)是獨(dú)立的 。當(dāng)然也是全部輸出。

我們可以在for語句中使用雙引號" "看出兩個變量的區(qū)別,

Shell腳本如下:

#!/bin/bash
#By author test.net test
for i in "$*";do
echo $i
done
echo "================="
for i in "$@";do
echo $i
done

執(zhí)行測試:

[root@localhost ~]# bash test_num.sh 1 2 3 4 5
1 2 3 4 5
=================
1
2
3
4
5
Shell編程之環(huán)境變量

Shell常見的變量之二環(huán)境變量,主要是在程序運(yùn)行時需要設(shè)置,環(huán)境變量詳解如下:

PATH                命令所示路徑,以冒號為分割;
HOME 打印用戶家目錄;
SHELL 顯示當(dāng)前Shell類型;
USER 打印當(dāng)前用戶名;
ID?? 打印當(dāng)前用戶id信息;
PWD?? 顯示當(dāng)前所在路徑;
TERM 打印當(dāng)前終端類型;
HOSTNAME???? 顯示當(dāng)前主機(jī)名。

環(huán)境變量相關(guān)文件:

系統(tǒng)級:

系統(tǒng)級變量文件對所有用戶生效。

  • /etc/profile # 系統(tǒng)范圍內(nèi)的環(huán)境變量和啟動文件。不建議把要做的事情寫在這里面,最好創(chuàng)建一個自定義的,放在/etc/profile.d 下

  • /etc/bashrc # 系統(tǒng)范圍內(nèi)的函數(shù)和別名

用戶級:

用戶級變量文件對自己生效,都在自己家目錄下。

  • ~/.bashrc # 用戶指定別名和函數(shù)

  • ~/.bash_logout # 用戶退出執(zhí)行

  • ~/.bash_profile # 用戶指定變量和啟動程序

  • ~/.bash_history # 用戶執(zhí)行命令歷史文件

開啟啟動腳本順序:/etc/profile -> /etc/profile.d/*.sh -> ~/.bash_profile -> ~/.bashrc ->

/etc/bashrc

因此,我們可以把寫的腳本放到以上文件里執(zhí)行。

Shell編程之用戶變量

Shell常見的變量之三用戶變量,用戶變量又稱為局部變量,主要用在Shell腳本內(nèi)部或者臨時局部使用,系統(tǒng)變量詳解如下:

A=test.net???????????????????? 自定義變量A;
N_SOFT=nginx-1.12.0.tar.gz?????? 自定義變量N_SOFT;
BACK_DIR=/data/backup/?????????? 自定義變量BACK_DIR;
IP1=192.168.1.11?????????????? 自定義變量IP1;
IP2=192.168.1.12?????????????? 自定義變量IP2。

創(chuàng)建Echo打印菜單Shell腳本,腳本代碼如下:

#!/bin/bash
#auto install nginx
#By author test.net
echo -e '\033[32m-----------------------------\033[0m'
FILE=nginx-1.16.0.tar.gz
URL=http://nginx.org/download
PREFIX=/usr/local/nginx/
echo -e "\033[36mPlease Select Install Menu:\033[0m"
echo
echo "1)官方下載nginx文件包."
echo "2)解壓nginx源碼包."
echo "3)編譯安裝nginx服務(wù)器."
echo "4)啟動nginx服務(wù)器."
echo -e '\033[32m-----------------------------\033[0m'
sleep 20
Shell編程之標(biāo)準(zhǔn)輸入、輸出和錯誤

關(guān)于文件描述符(fd)的基本概念:

文件描述符是一個非負(fù)整數(shù),在打開現(xiàn)存文件或新建文件時,內(nèi)核會返回一個文件描述符,讀寫文件也需要使用文件描述符來訪問文件。內(nèi)核為每個進(jìn)程維護(hù)該進(jìn)程打開的文件記錄表。文件描述符只適于 Unix、Linux 操作系統(tǒng)。

文件描述符列表(標(biāo)準(zhǔn)輸入、輸出和錯誤)

系統(tǒng)中共有12個文件描述符,0、1、2分別是標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯誤,3到9是可以被任意使用的。

每一個unix進(jìn)程,都會擁有三個標(biāo)準(zhǔn)的文件描述符,來對應(yīng)三種不同的身份。

文件

描述符
描述
映射關(guān)系

0 標(biāo)準(zhǔn)輸入
鍵盤
/dev/stdin --> /proc/self/fd/0

1 標(biāo)準(zhǔn)輸出
屏幕
/dev/stdin --> /proc/self/fd/1

2 標(biāo)準(zhǔn)錯誤
屏幕
/dev/stderr --> /proc/self/fd/2

每一個文件描述符會對應(yīng)一個打開文件,同時不同的文件描述符也可以對應(yīng)同一個打開文件;同一個文件可以被不同的進(jìn)程打開,也可以被同一個進(jìn)程多次打開。

在/proc/PID/fd中,列舉了進(jìn)程PID所擁有的文件描述符,例如

[root@localhost ~]# cat learn_redirect.sh 
#!/bin/bash
source /etc/profile;
# $$表示當(dāng)前進(jìn)程的PID
PID=$$
# 查看當(dāng)前進(jìn)程的文件描述符指向
ls -l /proc/$PID/fd
echo "-------------------";echo
# 文件描述符1與文件tempfd1進(jìn)行綁定
( [ -e ./tempfd1 ] || touch ./tempfd1 ) && exec 1<>./tempfd1
# 查看當(dāng)前進(jìn)程的文件描述符指向
ls -l /proc/$PID/fd
echo "-------------------";echo;

腳本執(zhí)行的結(jié)果如下:

[root@localhost ~]# cat testfd1 
total 0
lrwx------ 1 root root 64 Sep 14 20:55 0 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 14 20:55 1 -> /root/testfd1
lrwx------ 1 root root 64 Sep 14 20:55 2 -> /dev/pts/0
lr-x------ 1 root root 64 Sep 14 20:55 255 -> /root/test.sh
[root@localhost ~]# sh test.sh
total 0
lrwx------ 1 root root 64 Sep 14 20:55 0 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 14 20:55 1 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 14 20:55 2 -> /dev/pts/0
lr-x------ 1 root root 64 Sep 14 20:55 255 -> /root/test.sh

上述的例子中第9行,將文件描述符1與文件testfile進(jìn)行了綁定,此后,文件描述符1指向了testfile文件,標(biāo)準(zhǔn)輸出被重定向到了文件testfile中。

重定向符號詳解
符號  	描述
>			符號左邊輸出作為右邊輸入(標(biāo)準(zhǔn)輸出)
>>    		符號左邊輸出追加右邊輸入
<			符號右邊輸出作為左邊輸入(標(biāo)準(zhǔn)輸入)
<<			符號右邊輸出追加左邊輸入
&			重定向綁定符號

輸入和輸出可以被重定向符號解釋到 shell,shell 命令是從左到右依次執(zhí)行命令。
重定向輸出

1)覆蓋輸出

一般格式:[n] > file,如果 n 沒有指定,默認(rèn)是 1

示例:

打印結(jié)果寫到文件:

echo "test" > a.txt

當(dāng)沒有安裝 bc 計算器時,錯誤輸出結(jié)果寫到文件:

echo "1 + 1" |bc 2 > error.log

2)追加重定向輸出

一般格式:[n] >> file,如果 n 沒有指定,默認(rèn)是 1

示例:

打印結(jié)果追加到文件:

echo "test" >> a.txt

當(dāng)沒有安裝 bc 計算器時,錯誤輸出結(jié)果追加文件:

echo "1 + 1" |bc 2> error.log
重定向輸入

一般格式:[n]<word,如果 n 沒有指定,默認(rèn)是 0

示例:

a.txt 內(nèi)容作為 grep 輸入:

grep "test" --color < a.txt
重定向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤

1)覆蓋重定向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤

&>file 和>&file 等價于 >file 2>&1
&將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)輸入綁定到一起,重定向 word 文件。

示例:

當(dāng)不確定執(zhí)行對錯時都覆蓋到文件:

echo "1 + 1" |bc &> error.log

當(dāng)不確定執(zhí)行對錯時都覆蓋到文件:

echo "1 + 1" |bc > error.log 2>&1

2)追加重定向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤

&>>file 等價于>>file 2>&1

示例:

當(dāng)不確定執(zhí)行對錯時都追加文件:

echo "1 + 1" |bc &>> error.log

將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)輸入追加重定向到 delimiter:

<< delimiter
here-document
delimiter

從當(dāng)前 shell 讀取輸入源,直到遇到一行只包含 delimiter 終止,內(nèi)容作為標(biāo)準(zhǔn)輸入。

將 eof 標(biāo)準(zhǔn)輸入作為 cat 標(biāo)準(zhǔn)輸出再寫到 a.txt:

# cat << eof
123
abc
eof
123
abc
# cat > a.txt << eof
> 123
> abc
> eof
重定向到空設(shè)備

/dev/null 是一個空設(shè)備,向它寫入的數(shù)據(jù)都會丟棄,但返回狀態(tài)是成功的。與其對應(yīng)的還有一個/dev/zero 設(shè)備,提供無限的 0 數(shù)據(jù)流。

在寫 Shell 腳本時我們經(jīng)常會用到/dev/null 設(shè)備,將 stdout、stderr 輸出給它,也就是我們不想要這些輸出的數(shù)據(jù)。

通過重定向到/dev/null 忽略輸出,比如我們沒有安裝 bc 計算器,正常會拋出沒有發(fā)現(xiàn)命令:

echo "1 + 1" |bc >/dev/null 2>&1

這就讓標(biāo)準(zhǔn)和錯誤輸出到了空設(shè)備。

忽略標(biāo)準(zhǔn)輸出:

echo "test" >/dev/null

忽略錯誤輸出:

echo "1 + 1" |bc 2>/dev/null

注意:上個練習(xí)提到的2>&1可以這樣理解

對于&1 更準(zhǔn)確的說應(yīng)該是文件描述符 1,而1標(biāo)識標(biāo)準(zhǔn)輸出,stdout。

對于2 ,表示標(biāo)準(zhǔn)錯誤,stderr。

2>&1 的意思就是將標(biāo)準(zhǔn)錯誤重定向到標(biāo)準(zhǔn)輸出。這里標(biāo)準(zhǔn)輸出已經(jīng)重定向到了 /dev/null。那么標(biāo)準(zhǔn)錯誤也會輸出到/dev/null

exec 命令詳解

exec 是 bash 的內(nèi)置命令,shell 的內(nèi)置命令exec執(zhí)行命令時,不啟用新的shell進(jìn)程。

source 和. 不啟用新的shell,在當(dāng)前shell中執(zhí)行,設(shè)定的局部變量在執(zhí)行完命令后仍然有效。

bash 或 sh 或 shell script 執(zhí)行時,另起一個子shell,其繼承父shell的環(huán)境變量,其子shell的變量執(zhí)行完后不影響父shell。exec是用被執(zhí)行的命令行替換掉當(dāng)前的shell進(jìn)程,且exec命令后的其他命令將不再執(zhí)行。例如在當(dāng)前shell中執(zhí)行 exec ls 表示執(zhí)行l(wèi)s這條命令來替換當(dāng)前的shell ,即為執(zhí)行完后會退出當(dāng)前shell。

為了避免這個結(jié)果的影響,一般將exec命令放到一個shell腳本中,用主腳本調(diào)用這個腳本,調(diào)用處可以用bash xx.sh(xx.sh為存放exec命令的腳本),這樣會為xx.sh建立一個子shell去執(zhí)行,當(dāng)執(zhí)行exec后該子腳本進(jìn)程就被替換成相應(yīng)的exec的命令。其中有一個例外:當(dāng)exec命令對文件描述符操作的時候,就不會替換shell,而是操作完成后還會繼續(xù)執(zhí)行后面的命令!

常用格式:exec [-cl] [-a name] [command [arguments]]

如果指定了command,它將用當(dāng)前的command替換當(dāng)前的shell, 但是不會產(chǎn)生新的進(jìn)程,如果有arguments參數(shù),將會作為command的參數(shù)。

選項:

-l:將會在傳遞給command命令的第0個參數(shù)前面加上一個dash('-'),有點(diǎn)像在用su的時候(su - username)
-c:將會使command命令在一個空環(huán)境中執(zhí)行
-a:shell會將name作為第0個參數(shù)傳遞給要執(zhí)行的command命令

exec 語法:

exec命令
作用

exec ls
在shell中執(zhí)行l(wèi)s,ls結(jié)束后不返回原來的shell中了

exec <>
將file中的內(nèi)容作為exec的標(biāo)準(zhǔn)輸入

exec >file
將file中的內(nèi)容作為標(biāo)準(zhǔn)寫出

exec 3<>
將file讀入到fd3中

sort <&3
fd3中讀入的內(nèi)容被分類

exec 4>file
將寫入fd4中的內(nèi)容寫入file中

ls >&4
Ls將不會有顯示,直接寫入fd4中了,上面file中

exec 5<&4
創(chuàng)建fd4的拷貝fd5

exec 3<&-
關(guān)閉fd3

舉例:

先上我們進(jìn)如/dev/fd/目錄下看一下:

root@localhost #cd /dev/fd
root@localhost #/dev/fd#ls
0  1  2  255

root@localhost #/dev/fd#ls

0 1 2 255

默認(rèn)會有這四個項:

0是標(biāo)準(zhǔn)輸入,默認(rèn)是鍵盤。

1是標(biāo)準(zhǔn)輸出,默認(rèn)是屏幕/dev/tty

2是標(biāo)準(zhǔn)錯誤,默認(rèn)也是屏幕

255

當(dāng)我們執(zhí)行exec 3>/root/test,再去看看/dev/fd,一定多個3,什么意思呢?

也就是又增加了一個設(shè)備,這里也可以體會下linux設(shè)備即文件的理念。這時候fd3就相當(dāng)于一個管道了,重定向到fd3中的文件會被寫在test中。關(guān)閉這個重定向可以用exec 3>&-

read 命令

read 命令從標(biāo)準(zhǔn)輸入讀取,并把輸入的內(nèi)容復(fù)制給變量。

命令格式: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-pprompt] [-t timeout] [-u fd] [name ...]

-e  在一個交互 shell 中使用 readline 獲取行
-r  不允許反斜杠轉(zhuǎn)義任何字符
-s  隱藏輸入
-a array  保存為數(shù)組,元素以空格分隔
-d delimiter  持續(xù)讀取直到遇到 delimiter 第一個字符退出
-n nchars  讀取 nchars 個字符返回,而不是等到換行符
-p prompt  提示信息
-t timeout  等待超時時間,秒
-u fd  指定文件描述符號碼作為輸入,默認(rèn)是 0

示例:

  1. 獲取用戶輸入保存到變量:

[root@localhost ~]# read -p "Please input your name: " VAR
Please input your name: test
[root@localhost ~]# echo $VAR
test
  1. 用戶輸入保存為數(shù)組:

[root@localhost ~]# read -p "Please input your name: " -a ARRAY
Please input your name: 1 2 3 4 5
[root@localhost ~]# echo ${ARRAY[*]}
1 2 3 4 5
[root@localhost ~]# echo ${ARRAY[1]}
2
[root@localhost ~]# echo ${ARRAY[0]}
1
  1. 遇到 e 字符返回:

[root@localhost ~]# read -d e VAR
jf666
e
[root@localhost ~]# echo $VAR
jf666
  1. 從文件作為 read 標(biāo)準(zhǔn)輸入:

[root@localhost ~]# cat a.txt
test
[root@localhost ~]# read VAR < a.txt
[root@localhost ~]# echo $VAR
test
  1. while 循環(huán)讀取每一行作為 read 的標(biāo)準(zhǔn)輸入:

[root@localhost ~]# cat a.txt
test
test1
test2
[root@localhost ~]# cat a.txt |while read LINE; do echo $LINE; done
test
test1
test2

分別變量賦值:

[root@localhost ~]# read a b c
1 2 3
[root@localhost ~]# echo $a
1
[root@localhost ~]# echo $b
2
[root@localhost ~]# echo $c
3
[root@localhost ~]# echo 1 2 3 | while read a b c;do echo "$a $b $c"; done
1 2 3
管道符 ”|”

在Unix或類Unix操作系統(tǒng)中,管道是一個由標(biāo)準(zhǔn)輸入輸出鏈接起來的進(jìn)程集合,因此,每一個進(jìn)程的輸出將直接作為下一個進(jìn)程的輸入。

linux管道包含兩種

  • 匿名管道(ps aux | grep nginx)

  • 命名管道(mkfifo /tmp/fd1)

管道有一個特點(diǎn),如果管道中沒有數(shù)據(jù),那么取管道數(shù)據(jù)的操作就會滯留,直到管道內(nèi)進(jìn)入數(shù)據(jù),然后讀出后才會終止這一操作;同理,寫入管道的操作如果沒有讀取管道的操作,這一動作就會滯留。

匿名管道

在Unix或類Unix操作系統(tǒng)的命令行中,匿名管道使用ASCII中垂直線|作為匿名管道符,匿名管道的兩端是兩個普通的,匿名的,打開的文件描述符:一個只讀端和一個只寫端,這就讓其它進(jìn)程無法連接到該匿名管道。例如:cat file | less

為了執(zhí)行上面的指令,Shell創(chuàng)建了兩個進(jìn)程來分別執(zhí)行cat和less。

有一點(diǎn)值得注意的是兩個進(jìn)程都連接到了管道上,這樣寫入進(jìn)程cat就將其標(biāo)準(zhǔn)輸出(文件描述符為fd 1)連接到了管道的寫入端,讀取進(jìn)程less就將其標(biāo)準(zhǔn)輸入(文件描述符為fd 0)連接到了管道的讀入端。實際上,這兩個進(jìn)程并不知道管道的存在,它們只是從標(biāo)準(zhǔn)文件描述符中讀取數(shù)據(jù)和寫入數(shù)據(jù)。shell必須要完成相關(guān)的工作。

命名管道

命名管道簡介

命名管道也稱FIFO(FIFO,F(xiàn)irst In First Out),從語義上來講,F(xiàn)IFO其實與匿名管道類似,但值得注意:

  1. 在文件系統(tǒng)中,F(xiàn)IFO擁有名稱,并且是以設(shè)備特俗文件的形式存在的;

  2. 任何進(jìn)程都可以通過FIFO共享數(shù)據(jù);

  3. 除非FIFO兩端同時有讀與寫的進(jìn)程,否則FIFO的數(shù)據(jù)流通將會阻塞;

  4. 匿名管道是由shell自動創(chuàng)建的,存在于內(nèi)核中;而FIFO則是由程序創(chuàng)建的(比如mkfifo命令),存在于文件系統(tǒng)中;

  5. 匿名管道是單向的字節(jié)流,而FIFO則是雙向的字節(jié)流;

比如,可以利用FIFO實現(xiàn)單服務(wù)器、多客戶端的應(yīng)用程序:利用FIFO實現(xiàn)單服務(wù)器多客戶端的應(yīng)用程序

有了上面的知識準(zhǔn)備,現(xiàn)在可以開始講述,linux多進(jìn)程并發(fā)時,如何控制每次并發(fā)的進(jìn)程數(shù)。

命名管道特性

  • 如果管道內(nèi)容為空,則阻塞

  • 如果沒有讀管道的操作,則阻塞

測試命名管道特性

  1. 如果管道內(nèi)容為空,則阻塞cat /tmp/fd,管道內(nèi)容為空則阻塞

10.0.0.7終端1:操作命令
[root@localhost fd]# mkfifo  /tmp/fd1
[root@localhost fd]# cat /tmp/fd1 
10.0.0.7終端2:操作命令
[root@localhost ~]# echo "test" > /tmp/fd1
查看終端1 返回
[root@localhost fd]# cat /tmp/fd1 
test

2.如果沒有讀管道的操作,則阻塞echo "test" > /tmp/fd1,沒有讀管道則阻塞

查看10.0.0.7終端1
[root@localhost fd]# echo "test" > /tmp/fd1
查看10.0.0.7終端2
[root@localhost ~]# cat /tmp/fd1 
test

總結(jié):

利用有名管道的上述特性就可以實現(xiàn)一個隊列控制了。

舉例:一個女士公共廁所總共就10個蹲位,這個蹲位就是隊列長度,女廁所門口放著10把藥匙,要想上廁所必須拿一把藥匙,上完廁所后歸還藥匙,下一個人就可以拿鑰匙進(jìn)去上廁所了,這樣同時來了1千位美女上廁所,那前十個人搶到藥匙進(jìn)去上廁所了,后面的990人需要等一個人出來歸還藥匙才可以拿到藥匙進(jìn)去上廁所,這樣10把藥匙就實現(xiàn)了控制1000人上廁所的任務(wù)(os中稱之為信號量)。

注意:

(1)管道具有存一個讀一個,讀完一個就少一個,沒有則阻塞,放回的可以重復(fù)取,這正是隊列特性,但是問題是當(dāng)往管道文件里面放入一段內(nèi)容,沒人取則會阻塞,這樣你永遠(yuǎn)也沒辦法,往管道里面同時放入10段內(nèi)容(想當(dāng)與10把藥匙),解決這個問題的關(guān)鍵就是文件描述符了。

(2)mkfifo /tmp/fd1

創(chuàng)建有名管道文件exec 3<>/tmp/fd1,創(chuàng)建文件描述符3關(guān)聯(lián)管道文件,這時候3這個文件描述符就擁有了管道的所有特性,還具有一個管道不具有的特性:無限存不阻塞,無限取不阻塞,而不用關(guān)心管道內(nèi)是否為空,也不用關(guān)心是否有內(nèi)容寫入引用文件描述符: &3可以執(zhí)行n次echo >&3 往管道里放入n把鑰匙。

Shell編程之常用Linux系統(tǒng)配置文件解析

常用配置文件詳解:

# 查看系統(tǒng)信息
/etc/redhat-release  系統(tǒng)版本

/etc/hosts  主機(jī)名與 IP 對應(yīng)關(guān)系

/etc/resolv.conf  DNS 服務(wù)器地址

/etc/hostname  主機(jī)名

/etc/sysctl.conf  系統(tǒng)參數(shù)配置文件

/etc/sudoers  sudo 權(quán)限配置

/etc/init.d  	服務(wù)啟動腳本

/etc/sysconfig/network-scripts      網(wǎng)卡信息配置目錄

/etc/rc.d/rc.local   				系統(tǒng) init 初始化完后執(zhí)行,不建議將啟動服務(wù)寫在這里面,應(yīng)創(chuàng)建自己的 systemd 或 udev

/etc/fstab  硬盤自動掛載配置

/etc/crontab 系統(tǒng)級任務(wù)計劃

/var/spool/cron  用戶級任務(wù)計劃,此目錄下以用戶名命名對應(yīng)每個用戶的任務(wù)計劃

/etc/cron.d  描述計算機(jī)任務(wù)計劃

/etc/hosts.allow  TCP 包訪問列表

/etc/hosts.deny  TCP 包拒絕列表

/usr/share/doc  各軟件的文檔

/etc/sshd_config  SSH 服務(wù)配置文件

/var/log  系統(tǒng)和應(yīng)用程序日志目錄

/var/spool/mail  郵件目錄

# /dev  目錄

/dev 目錄下存放的是一些設(shè)備文件。

/dev/hd[a-t]  IDE 設(shè)備

/dev/sd[a-z]  SCSI 設(shè)備

/dev/dm-[-9]  LVM 邏輯磁盤

/dev/null  黑洞

/dev/zero  無限 0 數(shù)據(jù)流

# /proc  目錄

/proc 是一個虛擬目錄,在 Linux 系統(tǒng)啟動后生成的,數(shù)據(jù)存儲在內(nèi)存中,存放內(nèi)核運(yùn)行時的參數(shù)、網(wǎng)絡(luò)信息、進(jìn)程狀態(tài)等等。

/proc主目錄

/proc/[0-9]+  此目錄下數(shù)字命名的目錄是運(yùn)行進(jìn)程信息,目錄名為 PID

/proc/meminfo  物理內(nèi)存、交換空間等信息,free

/proc/loadavg  系統(tǒng)負(fù)載

/proc/uptime 系統(tǒng)運(yùn)行時間

計算系統(tǒng)啟動和運(yùn)行時間:

cat /proc/uptime| awk -F. '{run_days=$1 / 86400;run_hour=($1 % 86400)/3600;run_minute=($1 % 3600)/60;run_second=$1 % 60;printf("系統(tǒng)已運(yùn)行:%d天%d時%d分%d秒",run_days,run_hour,run_minute,run_second)}'

或 who –b  查看最后一次系統(tǒng)啟動的時間

/proc/cpuinfo  CPU 信息

/proc/modules  系統(tǒng)已加載的模塊或驅(qū)動,lsmod

/proc/mounts  文件系統(tǒng)掛載信息,mount

/proc/swaps  swap 分區(qū)信息

/proc/partitions  系統(tǒng)分區(qū)信息

/proc/version  內(nèi)核版本

/proc/stat  CPU 利用率,磁盤,內(nèi)存頁

/proc/devices  可用的設(shè)備列表

/proc/net 網(wǎng)絡(luò)目錄

/proc/net 目錄存放的是一些網(wǎng)絡(luò)協(xié)議信息。

/proc/net/tcp  TCP 狀態(tài)連接信息,netstat

/proc/net/udp  UDP 狀態(tài)連接信息

/proc/net/arp  arp 信息表

/proc/net/dev  網(wǎng)卡流量

/proc/net/snmp  網(wǎng)絡(luò)傳輸協(xié)議的收發(fā)包信息

/proc/net/sockstat  socket 使用情況,比如已使用,正在使用

/proc/net/netstat  網(wǎng)絡(luò)統(tǒng)計數(shù)據(jù),netstat -s

/proc/net/route  路由表

/proc/sys 系統(tǒng)內(nèi)核目錄

這個目錄下的文件可被讀寫,存了大多數(shù)內(nèi)核參數(shù),可以修改改變內(nèi)核行為。所以修改這些文件要特別小心,修改錯誤可能導(dǎo)致內(nèi)核不穩(wěn)定。

有四個主要的目錄:
fs # 文件系統(tǒng)各方面信息,包括配額、文件句柄、inode 和目錄項。
kernel # 內(nèi)核行為的信息
net # 網(wǎng)絡(luò)配置信息,包括以太網(wǎng)、ipx、ipv4 和 ipv6。
vm # Linux 內(nèi)核的虛擬內(nèi)存子系統(tǒng),通常稱為交換空間。

# 內(nèi)核配置文件
/proc/sys/fs/file-max 		內(nèi)核分配所有進(jìn)程最大打開文件句柄數(shù)量,可適當(dāng)增加此值
/proc/sys/fs/file-nr  		只讀,第一個值已分配的文件句柄數(shù)量,第二個值分配沒有使用文件句柄數(shù)量,第三個值文件句柄最大數(shù)量。

/proc/sys/kernel/ctrl-alt-del 	組合鍵重啟計算機(jī),只為 0 同步緩沖區(qū)到磁盤,1 為不同步

/proc/sys/kernel/domainname     配置系統(tǒng)域名

/proc/sys/kernel/exec-shield	配置內(nèi)核執(zhí)行保護(hù)功能,防止某類型緩沖區(qū)溢出***。0 為禁用,1 開啟

/proc/sys/kernel/hostname  配置系統(tǒng)主機(jī)名

/proc/sys/kernel/osrelease  內(nèi)核版本號

/proc/sys/kernel/ostype  操作系統(tǒng)類型

/proc/sys/kernel/shmall  設(shè)置共享內(nèi)存的總量,以字節(jié)為單位

/proc/sys/kernel/shmmax  設(shè)置最大共享內(nèi)存段

/proc/sys/kernel/shmmni  設(shè)置共享內(nèi)存段最大數(shù)量

/proc/sys/kernel/threads-max  設(shè)置最大允許線程數(shù)量

/proc/sys/kernel/pid_max  設(shè)置最大允許創(chuàng)建的 pid 數(shù)量

/proc/sys/kernel/version  顯示最后一次編譯內(nèi)核時間

/proc/sys/kernel/random/uuid  生成 uuid

/proc/sys/kernel/core_pattern  控制生成 core dump 文件位置和保存格式

/proc/sys/net/core/netdev_max_backlog  設(shè)置數(shù)據(jù)包隊列允許最大數(shù)量

/proc/sys/net/core/optmem_max  設(shè)置 socket 允許最大緩沖區(qū)大小

/proc/sys/net/core/somaxconn  每個端口最大監(jiān)聽隊列長度

/proc/sys/net/core/rmem_default  設(shè)置 socket 接收默認(rèn)緩沖區(qū)大小,單位字節(jié)

/proc/sys/net/core/rmem_max  設(shè)置 socket 接收最大緩沖區(qū)大小

/proc/sys/net/core/wmem_default  設(shè)置 socket 發(fā)送默認(rèn)緩沖區(qū)大小

/proc/sys/net/core/wmem_max  設(shè)置 socket 發(fā)送最大緩沖區(qū)大小

/proc/sys/net/ipv4/icmp_echo_ignore_all 和 icmp_echo_ignore_broadcasts  設(shè)置是否忽略 icmp 響應(yīng)包和廣播包,0 為不忽略,1 為忽略  

/proc/sys/net/ipv4/ip_default_ttl  設(shè)置默認(rèn)生存時間

/proc/sys/net/ipv4/ip_forward       允許系統(tǒng)接口轉(zhuǎn)發(fā)數(shù)據(jù)包,默認(rèn) 0 為關(guān)閉,1 為開啟

/proc/sys/net/ipv4/ip_local_port_range   指定使用本地 TCP 或 UDP 端口范圍,第一個值最低,第二個值最高

/proc/sys/net/ipv4/tcp_syn_retries  	限制重新發(fā)送 syn 嘗試建立連接次數(shù)

/proc/sys/net/ipv4/tcp_synack_retries  syn ack 確認(rèn)包嘗試次數(shù)/proc/sys/net/ipv4/tcp_syncookies      是否啟用 syn cookie,0 為關(guān)閉,默認(rèn) 1 為開啟


/proc/sys/net/ipv4/tcp_max_tw_buckets  系統(tǒng)保持 TIME_WAIT 最大數(shù)量

/proc/sys/net/ipv4/tcp_tw_recycle   是否啟用 TIME_WAIT 快速收回,默認(rèn) 0 為關(guān)閉,1 為開啟

/proc/sys/net/ipv4/tcp_tw_reuse     是否啟用 TIME_WAIT 復(fù)用,默認(rèn) 0 為關(guān)閉,1為開啟

/proc/sys/net/ipv4/tcp_keepalive_time		TCP 連接保持時間(默認(rèn) 2 小時),當(dāng)連接活動,定時器會重新復(fù)位。
/proc/sys/vm/swappiness			內(nèi)核按此值百分比來使用 swap,值越小越不考慮使用物理內(nèi)存,0 為盡可能不使用 swap

/proc/sys/vm/overcommit_memory		控制內(nèi)存分配,默認(rèn) 0 為內(nèi)核先評估可用內(nèi)存,如果足夠允許申請,否則拒絕,1 為允許分配所有物理內(nèi)存,2 為允許分配超過物理內(nèi)存和交換空間總和的內(nèi)存

/proc/sys/vm/overcommit_ratio		指定物理內(nèi)存比率,當(dāng) overcommit_memory=2時,用戶空間進(jìn)程可使用的內(nèi)存不超過物理內(nèi)存*overcommit_ratio+swap

Shell編程語句和實戰(zhàn)

Shell編程也叫Shell流程控制語句,流程控制主要是改變程序運(yùn)行順序的指令。

If條件語句實戰(zhàn)

Linux Shell編程中,if、for、while、case等條件流程控制語句用的非常多,熟練掌握以上流程控制語句及語法的實驗,對編寫Shel腳本有非常大的益處。

If條件判斷語句,通常以if開頭,fi結(jié)尾。也可加入else或者elif進(jìn)行多條件的判斷,if表達(dá)式如下:

if  (表達(dá)式) 
語句1
else
語句2
Fi

單分支格式1:if 條件 ; then 語句; fi
雙分支格式2:if 條件; then 語句; else 語句; fi
多分支格式3:if …; then … ;elif …; then …; else …; fi

If常見判斷邏輯運(yùn)算符詳解:
-f	 					判斷文件是否存在 eg: if [ -f filename ];
-d	 					判斷目錄是否存在 eg: if [ -d dir     ];
-eq						等于,應(yīng)用于整型比較 equal;
-ne						不等于,應(yīng)用于整型比較 not equal;
-lt						小于,應(yīng)用于整型比較 letter;
-gt						大于,應(yīng)用于整型比較 greater;
-le						小于或等于,應(yīng)用于整型比較;
-ge 					大于或等于,應(yīng)用于整型比較;
-a						雙方都成立(and) 邏輯表達(dá)式 –a 邏輯表達(dá)式;
-o						單方成立(or) 邏輯表達(dá)式 –o 邏輯表達(dá)式;
-z						“字符串”的長度為零則為真
-n                   “字符串”的長度為非零non-zero則為真
||      				單方成立;
&&      				雙方都成立表達(dá)式。

判斷符使用技巧:
1.整數(shù)比較使用-lt,-gt,ge等比較運(yùn)算符,詳情參考:整數(shù)比較
2.文件測試使用 -d, -f, -x等運(yùn)算發(fā),詳情參考:文件測試
3.邏輯判斷使用    &&(且)、||(或)、?。ㄈ》?
字符串實用的對比:
1.字符串的比較使用以下三個比較運(yùn)算符:= 或者(==)、!= 、> 、 <。
2.-z表示后面的值是否為空,為空則返回true,否則返回false。
3.-n表示判斷后面的值是否為空,不為空則返回true,為空則返回false。

邏輯判斷表達(dá)式:
if [ $a -gt $b ]; if [ $a -lt 5 ]; if [ $b -eq 10 ]等 -gt (>); -lt(<); -ge(>=); -le(<=);-eq(==); -ne(!=) 注意到處都是空格
可以使用 && || 結(jié)合多個條件
if [ $a -gt 5 ] && [ $a -lt 10 ]; then
if [ $b -gt 5 ] || [ $b -lt 3 ]; then

運(yùn)算工具( let/expr/bc )
命令	描述	示例
let	賦值并運(yùn)算,支持++,--	let VAR=(1+2)*3;echo $VAR
x=10;y=5
let x++;echo $x 每次執(zhí)行一次x加1
let y--;echo $y 每執(zhí)行一次y-1
let x+=2 每執(zhí)行一次x加2
let x-=2 沒執(zhí)行一次x減2
expr	乘法符號或者特殊符號需要加分斜杠轉(zhuǎn)義\* 	expr 1 \* 2  運(yùn)算符兩邊需要有空格
expr \( 1 + 2 \) \* 2 使用雙括號時要進(jìn)行轉(zhuǎn)義
bc	計算器,支持浮點(diǎn)運(yùn)算、平方	bc本身就是一個計算器,可以直接輸入命令,進(jìn)入解釋器。
echo “1 + 2” |bc 將管道符前面標(biāo)準(zhǔn)輸出左右bc的標(biāo)準(zhǔn)輸入
echo ‘scale=2;10/3’|bc 用scale保留2位小數(shù)點(diǎn)
If語句Shell腳本編程案例:

(1) 比較兩個整數(shù)大小。

#!/bin/bash
#By author test.net
NUM=100
if  (( $NUM > 4 )) ;then 
echo “The  Num  $NUM  more  than 4.”
else
echo “The  Num  $NUM  less   than 4.”
fi

(2) 判斷系統(tǒng)目錄是否存在。

#!/bin/bash
#judge DIR or Files
#By author test.net
if  [  !  -d  /data/20140515  -a  !  -d  /tmp/test/  ];then 
mkdir  -p  /data/20140515
fi

(3) if多個條件測試分?jǐn)?shù)判斷。

#!/bin/bash
#By author test.net
scores=$1
if  [[ $scores -eq 100 ]]; then
    echo "very good!";
elif [[ $scores -gt 85 ]]; then
    echo "good!";
elif [[ $scores -gt 60 ]]; then
    echo "pass!";
elif [[ $scores -lt 60 ]]; then
    echo "no pass!"
fi

(4) 根據(jù)Linux不同發(fā)行版本使用不同的命令進(jìn)行安裝軟件

#!/bin/bash
if [ -e /etc/redhat-release ]; then
yum install wget -y
elif [ $(cat /etc/issue |cut -d' ' -f1) == "Ubuntu" ]; then
apt-get install wget -y
else
Operating system cannot be found.
exit
fi
SHELL編程括號詳解

Shell編程中,尤其是使用if語句時,經(jīng)常會使用()、(())、[]、[[]]、{}等括號,如下為幾種括號簡單區(qū)別對比:

(  )
用于多個命令組、命令替換、初始化數(shù)組,多用于SHELL命令組,例如:JF=(jf1 jf2 jf3),其中括號左右不保留空格;定義變量時增加括號,括號內(nèi)的變量會失效
(( ))
整數(shù)擴(kuò)展、運(yùn)算符、重定義變量值,算術(shù)運(yùn)算比較,例如:((i++))、((i<=100)),其中括號左右不保留空格;
[ ]
bash內(nèi)部命令,[ ]與test是等同的,正則字符范圍、引用數(shù)組元素編號,不支持+-*/數(shù)學(xué)運(yùn)算符,邏輯測試使用-a、-o,通常用于字符串比較、整數(shù)比較以及數(shù)組索引,其中括號左右要保留空格;
[[ ]]
bash程序語言的關(guān)鍵字,不是一個命令,[[ ]]結(jié)構(gòu)比[ ]結(jié)構(gòu)更加通用,不支持+-*/數(shù)學(xué)運(yùn)算符,邏輯測試使用&&、||,通常用于字符串比較、邏輯運(yùn)算符等,其中括號左右要保留空格;
{}
主要用于命令集合或者范圍,例如mkdir  -p  /data/201{7,8}/,其中括號左右不保留空格;
SHELL編程符號詳解

Shell編程中,不管是使用變量、編程時,經(jīng)常會使用$、\、單引號、雙引號、反引號等符號,如下為幾種符號簡單區(qū)別對比:

  • 美元符號$,主要是用于引用SHELL編程中變量,例如定義變量JF=www.test.net,引用值,需要用$JF;

  • \反斜杠,主要是用于對特定的字符實現(xiàn)轉(zhuǎn)義,保留原有意義,例如echo “$JF”結(jié)果會打印$JF,而不會打印www.test.net;

  • 單引號 (' ') ,單引號,不具有變量置換的功能,所有的任意字符還原為字面意義,實現(xiàn)屏蔽Shell元字符的功能;

  • 雙引號(" ") ,雙引號,具有變量置換的功能,保留$(使用變量前導(dǎo)符), (轉(zhuǎn)義符), `(反向引號)元字符的功能;

  • 反向引號(),反引號,位于鍵盤Tab鍵上面一行的鍵,用作命令替換(相當(dāng)于$(...);

LAMP一鍵自動化安裝腳本

通過前面章節(jié)對if語句和變量的學(xué)習(xí),現(xiàn)基于所學(xué)知識,編寫一鍵源碼安裝LAMP腳本, 編寫腳本可以養(yǎng)成先分解腳本的各個功能的習(xí)慣,有利于快速寫出腳本,寫出更高效的腳本。

一鍵源碼安裝LAMP腳本,可以拆分為如下功能:

(1) LAMP打印菜單:

  1. 安裝apache WEB服務(wù)器;

  1. 安裝Mysql DB服務(wù)器;

  2. 安裝PHP 服務(wù)器;

  3. 整合LAMP架構(gòu)

  4. 啟動LAMP服務(wù);

(2) Apache服務(wù)器安裝部署:

Apache官網(wǎng)下載httpd-2.4.37.tar.gz版本,解壓,進(jìn)入安裝目錄,configure、make 、make install。

(3) Mysql服務(wù)器的安裝:

Mysql官網(wǎng)下載mysql-5.5.60.tar.gz版本,解壓,進(jìn)入安裝目錄,configure、make 、make install。

(4) PHP服務(wù)器安裝:

PHP官網(wǎng)下載php-5.4.31.tar.gz版本,解壓,進(jìn)入安裝目錄,configure、make 、make install。

一鍵源碼安裝LAMP腳本,auto_install_lamp.sh內(nèi)容如下:

#!/bin/bash
########## function ##########
depend_pkg ()
{
	yum install gcc gcc-c++ make cmake ncurses-devel libxml2-devel \
    perl-devel libcurl-devel libgcrypt libgcrypt-devel libxslt \
    libxslt-devel pcre-devel openssl-devel wget -y
}
cat <<END
        1.[install apache2.4]
        2.[install mysql5.5]
        3.[install php5.4]
END
read -p "Please input number : " NUM
case $NUM in
1)
########## Install Depend Pkg ##########
depend_pkg;
WorkDIR=/usr/local/src
cd $WorkDIR
[ -f "httpd-2.4.37.tar.gz" ] || wget http://mirrors.sohu.com/apache/httpd-2.4.37.tar.gz
ls *.tar.gz |xargs -I file tar xzf file -C $WorkDIR
if [ $? -eq 0 ];then
        yum install apr apr-devel apr-util apr-util-devel -y
else
        echo "------ apr make failed. ------"
    exit 1
fi
########## Install Apache ##########
HTTPDIR=/usr/local/apache2.4
if [ $? -eq 0 ];then
        cd $WorkDIR
        cd httpd-2.4.37
        ./configure -prefix=$HTTPDIR -enable-so -enable-rewrite -enable-modules=all
make && make install
else
        echo "------ apr-util make failed. ------"
        exit 1
fi
if [ $? -eq 0 ];then
        CONF=$HTTPDIR/conf/httpd.conf
        cp $HTTPDIR/bin/apachectl /etc/init.d/httpd
        chmod +x /etc/init.d/httpd
        sed -i "s/#ServerName www.example.com:80/ServerName ${IP}:80/g" $CONF
        sed -i 's/DirectoryIndex index.html/DirectoryIndex index.php index.html/g' $CONF
        sed -i "391 s/^/AddType application\/x-httpd-php .php/" $CONF
	/etc/init.d/httpd start
        IP=`ip address |grep inet|sed -n '3p'|awk '{print $2}'|awk -F/ '{print $1}'`
        Urlcode=`curl -o /dev/null -s -w "%{http_code}" $IP/index.html` 
	[ $Urlcode -eq 200 ] && echo "Apache install success." || echo "Apache install failed."
else
        echo "------ apache make failed. ------"
	exit 1
fi
;;
2)
########## Install Depend Pkg ##########
depend_pkg;
########## Install Mysql ##########
/usr/sbin/groupadd mysql
/usr/sbin/useradd -g mysql -s /sbin/nologin mysql
WorkDIR=/usr/local/src
MYSQLDIR=/usr/local/mysql5.5
cd $WorkDIR
[ -f "mysql-5.5.60.tar.gz" ] || wget https://mirrors.tuna.tsinghua.edu.cn/mysql/downloads/MySQL-5.5/mysql-5.5.60.tar.gz 
tar zxvf mysql-5.5.60.tar.gz
cd mysql-5.5.60
cmake -DCMAKE_INSTALL_PREFIX=$MYSQLDIR \
-DSYSCONFDIR=$MYSQLDIR/etc \
-DMYSQL_DATADIR=$MYSQLDIR/data \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci
make && make install
if [ $? -eq 0 ];then
	$MYSQLDIR/scripts/mysql_install_db \
--basedir=$MYSQLDIR --datadir=$MYSQLDIR/data/ --user=mysql 1>/dev/null
	mkdir $MYSQLDIR/etc
	cp support-files/my-medium.cnf $MYSQLDIR/etc/my.cnf
	cp support-files/mysql.server /etc/init.d/mysqld
	rm -rf /etc/my.cnf
#	echo "PATH=$PATH:$MYSQLDIR/bin" >> /etc/profile 
#	. /etc/profile
	chmod +x /etc/init.d/mysqld
	chown -R root.mysql $MYSQLDIR
	chown -R mysql.mysql $MYSQLDIR/data/
	/usr/local/mysql5.5/bin/mysqld_safe --user=mysql&
	sleep 10 && /usr/local/mysql5.5/bin/mysqladmin -u root password '123456'
	/usr/local/mysql5.5/bin/mysql -uroot -p'123456' -e "show databases;"
	[ $? -eq 0 ] && echo "MySQL install success." || echo "MySQL install failed."
else
	echo "------mysql cmake failed.------"
	exit 1 
fi
;;
3)
########## Install Depend Pkg ##########
depend_pkg;
########## Install GD ##########
yum install gd freetype freetype-devel libpng libpng-devel zlib zlib-devel libjpeg* -y
########## Install PHP ##########
WorkDIR=/usr/local/src
PHPDIR=/usr/local/php5.4
PHPCONF=$PHPDIR/etc/php.ini
cd $WorkDIR
[ -f "php-5.4.31.tar.gz" ] || wget http://mirrors.sohu.com/php/php-5.4.31.tar.gz
tar zxvf php-5.4.31.tar.gz 
cd php-5.4.31
./configure -prefix=$PHPDIR \
--with-config-file-path=$PHPDIR/etc \
--with-apxs2=/usr/local/apache2.4/bin/apxs \
--with-mysql=/usr/local/mysql5.5 \
--with-mysqli=/usr/local/mysql5.5/bin/mysql_config \
--enable-soap --enable-bcmath --enable-zip --enable-ftp \
--enable-mbstring --with-gd --with-libxml-dir --with-jpeg-dir \
--with-png-dir --with-freetype-dir --with-zlib \
--with-libxml-dir=/usr --with-curl --with-xsl --with-openssl
make && make install
if [ $? -eq 0 ];then
	\cp php.ini-production $PHPCONF
	echo "data.timezone = Asia\Shanghai" >> $PHPCONF
	sed -i 's/upload_max_filesize = 2M/ upload_max_filesize = 50M/g' $PHPCONF
	sed -i 's/display_errors = Off/display_errors = On/g' $PHPCONF
	echo "<?php phpinfo();?>" > /usr/local/apache2.4/htdocs/index.php
	/etc/init.d/httpd restart 
        /etc/init.d/mysqld restart &>/dev/null
        IP=`ip address |grep inet|sed -n '3p'|awk '{print $2}'|awk -F/ '{print $1}
'`
	Urlcode=`curl -o /dev/null -s -w "%{http_code}" $IP/index.php`
	[ $Urlcode -eq 200 ] && echo "PHP install success." || echo "PHP install failed."
    	echo "/usr/local/apache/bin/apachectl start" >> /etc/rc.local
    	chkconfig mysqld on
else
	echo "------ php make failed. ------"
fi
;;
*)
    echo "Please input number 1 2 3."
esac
循環(huán)語句For 和While

Shell 循環(huán)中分為當(dāng)直型循環(huán)和直到型循環(huán)

  1. 當(dāng)型循環(huán)結(jié)構(gòu):在每次執(zhí)行循環(huán)體前,對條件進(jìn)行判斷,當(dāng)條件滿足時,執(zhí)行循環(huán)體,否則終止循環(huán)。

  2. 直到型循環(huán)結(jié)構(gòu):在執(zhí)行了一次循環(huán)體后,對條件進(jìn)行判斷,如果條件不滿,就繼續(xù)執(zhí)行,知道條件滿足終止循環(huán)。

Shell編程中循環(huán)命令用于特定條件下決定某些語句重復(fù)執(zhí)行的控制方式,有三種常用的循環(huán)語句:for、while和until。

while循環(huán)和for循環(huán)屬于“當(dāng)型循環(huán)”,而until屬于“直到型循環(huán)”。

循環(huán)控制符:break和continue控制流程轉(zhuǎn)向。

For循環(huán)語句實戰(zhàn)

for循環(huán)語句主要用于對某個數(shù)據(jù)域進(jìn)行循環(huán)讀取、對文件進(jìn)行遍歷,通常用于需要循環(huán)某個文件或者列表。其語法格式以for…do開頭,done結(jié)尾。

語法格式如下:

For  變量  in  (表達(dá)式)
do
	語句1
done

For循環(huán)語句Shell腳本編程案例如下:

(1) 循環(huán)打印BAT企業(yè)官網(wǎng):

#!/bin/bash
#By author test.net
for  test  in  www.baidu.com www.taobao.com www.qq.com
do
	echo  $test
done

(2) 循環(huán)打印1至100數(shù)字,seq表示列出數(shù)據(jù)范圍:

#!/bin/bash
#By author test.net
for   i   in  `seq 1 100`
do
	echo  “NUM is $i”
done

(3) For循環(huán)求1-100的總和:

#!/bin/bash
#By author test.net
#auto sum 1 100
j=0
for  ((i=1;i<=100;i++))
do
     j=`expr $i + $j`
done
echo $j

(4) 對系統(tǒng)日志文件進(jìn)行分組打包:

#!/bin/bash
#By author test.net
for   i   in  `find /var/log  -name "*.log"`
do
        tar  -czf  `echo $i|sed s#/#_#g`.tgz  $i
done

(5) For循環(huán)批量遠(yuǎn)程主機(jī)文件傳輸:

#!/bin/bash
#auto scp files for client
#By author test.net
for i in `seq 100 200`
do
scp -r /tmp/test.txt root@192.168.1.$i:/data/webapps/www
done

(6) For循環(huán)批量遠(yuǎn)程主機(jī)執(zhí)行命令:

#!/bin/bash
#auto scp files for client
#By author test.net
for i in `seq 100 200`
do
       ssh -l  root 192.168.1.$i ‘ls /tmp’
done

(7) For循環(huán)打印10秒等待提示:

for ((j=0;j<=10;j++))
do 
	 echo  -ne  "\033[32m-\033[0m"
	 sleep 1 
done
echo

(8) 檢測多個域名是否可以正常訪問

#!/bin/bash 
URL="www.test.net www.sina.com www.jd.com" 
for url in $URL; do 
    HTTP_CODE=$(curl -o /dev/null -s -w %{http_code} http://$url) 
    if [ $HTTP_CODE -eq 200 -o $HTTP_CODE -eq 301 -o $HTTP_CODE -eq 302 ]; then 
        echo "$url OK." 
    else 
        echo "$url NO!" 
    fi 
done
[root@localhost scripts]# bash test.sh
www.baidu.com OK.
www.sina.com OK.
www.jd.com OK.

(9) For循環(huán)打印99乘法表

for i in  `seq 9`
do
         for n in `seq 9`
         do 
            [ $n -le $i ] &&  echo  -n  "$i*$n = `echo $(($i*$n))` "
         done 
        echo "  "
done
While循環(huán)語句實戰(zhàn)

While循環(huán)語句也稱為前測試循環(huán)語句,它的循環(huán)重復(fù)執(zhí)行次數(shù),是利用一個條件來控制是否繼續(xù)重復(fù)執(zhí)行這個語句。

While循環(huán)語句與for循環(huán)功能類似,主要用于對某個數(shù)據(jù)域進(jìn)行循環(huán)讀取、對文件進(jìn)行遍歷,通常用于需要循環(huán)某個文件或者列表,滿足循環(huán)條件會一直循環(huán),不滿足則退出循環(huán),其語法格式以while…do開頭,done結(jié)尾。

語法格式如下:

while  (表達(dá)式)
do
語句1
done

while循環(huán)語句之所以命名為前測試循環(huán),是因為它要先判斷此循環(huán)的條件是否成立,然后才作重復(fù)執(zhí)行的操作。

while循環(huán)語句執(zhí)行過程是:先判斷表達(dá)式的退出狀態(tài),如果退出狀態(tài)為0,則執(zhí)行循環(huán)體,并且在執(zhí)行完循環(huán)體后,進(jìn)行下一次循環(huán),否則退出循環(huán)執(zhí)行done后的命令。

為了避免死循環(huán),必須保證在循環(huán)體中包含循環(huán)出口條件,即存在表達(dá)式的退出狀態(tài)為非0的情況。

While循環(huán)語句Shell腳本編程案例如下:

(1) 循環(huán)打印BAT企業(yè)官網(wǎng),read指令用于讀取行或者讀取變量:

v1 版本
#!/bin/bash
#By author test.net
while read line
do 
echo $line
done <test.txt

v2版本讓循環(huán)的腳本只運(yùn)行2遍。
#!/bin/bash
#by author test.net
n=1
while ((n<=2));
do
	((n++))
	while read test;
	do
		echo $test;
		sleep 3;
	done < /root/test.txt
done

其中test.txt內(nèi)容為:

www.baidu.com
www.taobao.com
www.qq.com

(2) While無限每秒輸出Hello World:

#!/bin/bash
#By author test.net
while sleep 1
do  
echo -e "\033[32mHello World.\033[0m"
done
# while true表示條件永遠(yuǎn)為真,因此會一直運(yùn)行,像死循環(huán)一樣,但是我們稱呼為守護(hù)進(jìn)程。

(3) 循環(huán)打印1至100數(shù)字,expr用于運(yùn)算邏輯工具:

#!/bin/bash
#By author test.net
i=0
while ((i<=100))
do
        echo  $i
        i=`expr $i + 1`
done

(4) While循環(huán)求1-100的總和:

#!/bin/bash
#By author test.net
#auto sum 1 100
j=0
i=1
while ((i<=100))
do
     j=`expr $i + $j`
     ((i++))
done
echo $j
=================
#!/bin/bash 
i=1
j=0
while [ $i -le 100 ];do
	let j=j+i
	let i=i+1
done 
echo $j

(5) 條件表達(dá)式為true,產(chǎn)生死循環(huán),不間斷ping主機(jī)地址

#!/bin/bash 
#By author test.net
while true; do 
    ping –c 1 www.test.net
done

(6) While循環(huán)逐行讀取文件:

#!/bin/bash
#By author test.net
while read line
do
    echo  $line;
done  < /etc/hosts

(7) While循環(huán)判斷輸入IP正確性:

#!/bin/bash
#By author test.net
#Check  IP  Address
read -p "Please enter ip Address,example 192.168.0.11 ip": IPADDR
echo $IPADDR|grep -v "[Aa-Zz]"|grep --color -E "([0-9]{1,3}\.){3}[0-9]{1,3}"
while [ $? -ne 0 ]
do
        read -p "Please enter ip Address,example 192.168.0.11 ip": IPADDR
        echo $IPADDR|grep -v "[Aa-Zz]"|grep --color -E "([0-9]{1,3}\.){3}[0-9]{1,3}"
done

(8) 每5秒循環(huán)判斷/etc/passwd是否被非法修改:

#!/bin/bash
#Check File to change.
#By author test.net
FILES="/etc/passwd"
while true
do
        echo "The Time is `date +%F-%T`"
        OLD=`md5sum $FILES|cut -d" " -f 1`
        sleep 5
        NEW=`md5sum $FILES|cut -d" " -f 1`
        if [[ $OLD != $NEW ]];then
                echo "The $FILES has been modified."
        fi
done

(9) 每10秒循環(huán)判斷test用戶是否登錄系統(tǒng):

#!/bin/bash
#Check File to change. 
#By author test.net
USERS="test"
while true
do
        echo "The Time is `date +%F-%T`"
        sleep 10
        NUM=`who|grep "$USERS"|wc -l`
        if [[ $NUM -ge 1 ]];then
                echo "The $USERS is login in system."
        fi
done

Case選擇語句實戰(zhàn)

Case選擇語句,主要用于對多個選擇條件進(jìn)行匹配輸出,與if elif語句結(jié)構(gòu)類似,通常用于腳本傳遞輸入?yún)?shù),打印出輸出結(jié)果及內(nèi)容,其語法格式以Case…in開頭,esac結(jié)尾。

語法格式如下:

#!/bin/bash
#By author test.net
case  $1  in  
    Pattern1)
    語句1 
    ;;  
    Pattern2)
    語句2
    ;;  
    Pattern3)
    語句3
    ;;  
esac

Case條件語句Shell腳本編程案例如下:

(1) 打印Monitor及Archive選擇菜單:

#!/bin/bash
#By author test.net
case $1 in
        monitor)
        echo "monitor"
        ;;
        archive)
        echo "archive"
        ;;
        help )
        echo -e "\033[32mUsage:{$0 monitor | archive |help }\033[0m"
        ;;
        *)
        echo -e "\033[32mUsage:{$0 monitor | archive |help }\033[0m "
esac

(2) 自動修改IP腳本菜單:

#!/bin/bash
#By author test.net
case $i in
                modify_ip)
                change_ip
                ;;
                modify_hosts)
                change_hosts
                ;;
                exit)
                exit
                ;;
                *)
                echo -e "1) modify_ip\n2) modify_ip\n3)exit"  
esac
Select選擇語句實戰(zhàn)

Select語句一般用于選擇,常用于選擇菜單的創(chuàng)建,可以配合PS3來做打印菜單的輸出信息,其語法格式以select…in do開頭,done結(jié)尾:

select i in (表達(dá)式) 
do
語句
done

Select選擇語句Shell腳本編程案例如下:

(1) 打印開源操作系統(tǒng)選擇:

#!/bin/bash
#By author test.net
PS3="What you like most of the open source system?"
select i in CentOS RedHat Ubuntu 
do
echo "Your Select System: "$i
done

(2) 打印LAMP選擇菜單

#!/bin/bash
#By author test.net
PS3="Please enter you select install menu:"
select i in http php mysql quit
do
case $i in
        http)
        echo Test Httpd.
        ;;
        php)
        echo Test PHP.
        ;;
        mysql)
        echo Test MySQL.
        ;;
        quit)
        echo The System exit.
        exit
esac
done
break 和 和 continue 語句
  • break 是終止循環(huán)。

  • continue 是跳出當(dāng)前循環(huán)。

示例 1:在死循環(huán)中,滿足條件終止循環(huán)

#!/bin/bash 
i=0 
while true; do 
    let i++ 
    if [ $i -eq 3 ]; then 
        break 
    fi 
    echo $i 
done
 
# bash test.sh
1
2

上述腳本中首先是使用了while循環(huán)來引用let計算器,計算i的值,后面用了 if 判斷,并用了 break 語句,如果數(shù)字等于3就跳出循環(huán)。

示例 2:舉例子說明 continue 用法

#!/bin/bash
i=0
while [ $i -lt 5 ]; do
let i++
if [ $i -eq 3 ]; then
continue
fi
echo $i
done
# bash test.sh
1
2
4
5

注上述實驗在使用continue 是進(jìn)行做了一個判斷,如果i++ 大于等于到3的時候進(jìn)行跳出本次循環(huán),繼續(xù)下次循環(huán)。所以打印出來之后沒有數(shù)字3。

以上2個案例表明continue是用于跳出單此循環(huán)而使用,break則是匹配到之后則是跳出整個循環(huán)語句,即時沒有循環(huán)完,也會進(jìn)行跳出。

Shift 偏移
Shell編程函數(shù)實戰(zhàn)

Shell允許將一組命令集或語句形成一個可用塊,這些塊稱為Shell函數(shù),Shell函數(shù)的用于在于只需定義一次,后期隨時使用即可,無需在Shell腳本中添加重復(fù)的語句塊,其語法格式以function name(){開頭,以}結(jié)尾。

格式

Shell編程函數(shù)默認(rèn)不能將參數(shù)傳入()內(nèi)部,Shell函數(shù)參數(shù)傳遞在調(diào)用函數(shù)名稱傳遞,例如name args1 args2。

function name (){
        command1
command2
        ........
}
name args1 args2
#function關(guān)鍵字可寫,也可不寫。

引用函數(shù)

func [OPTION]

引用函數(shù)的時候只需要執(zhí)行函數(shù)名稱即可,OPTION是參數(shù),參數(shù)可以寫多個,和腳本后面的參數(shù)是一樣的

無參函數(shù)

[root@localhost scripts]# cat test.sh
 \#!/bin/bash 
 func() { 
     echo "This is a function." 
 } 
 func
 [root@localhost scripts]# bash test.sh
 This is a function.

Shell函數(shù)很簡單,函數(shù)名后跟雙括號,再跟雙大括號。通過函數(shù)名直接調(diào)用,不加小括號,函數(shù)命令可以自己定義。

有參函數(shù)

[root@localhost scripts]# cat test.sh
#!/bin/bash 
func() { 

    echo "Hello $1" 
} 
func world 
[root@localhost scripts]# bash test.sh
Hello world

通過Shell位置參數(shù)給函數(shù)傳參,參照執(zhí)行腳本時的$1,$2,$3 等示例。

函數(shù)返回值

[root@localhost scripts]# cat test.sh 
#!/bin/bash 
func() { 
   VAR=$((1+1)) 
    return $VAR 
    echo "This is a function." 
} 
func 
echo $?
[root@localhost scripts]# sh test.sh 
2

return在函數(shù)中定義狀態(tài)返回值,返回并終止函數(shù),但返回的只能是0-255的數(shù)字,類似于exit。

遞歸函數(shù)

函數(shù)也支持遞歸調(diào)用,也就是自己調(diào)用自己。

[root@localhost scripts]# cat test.sh 
#!/bin/bash 
test() { 
    echo $1 
    sleep 1 
    test hello 
} 
test
[root@localhost scripts]# bash test.sh

hello
hello
hello
hello
hello
……………

執(zhí)行會一直在調(diào)用本身打印hello,這就形成了閉環(huán)。

fork 炸彈

經(jīng)典的 fork 炸彈就是函數(shù)遞歸調(diào)用:

:(){ :|:& };: 或 .(){.|.&};.

這樣看起來不好理解,我們更改下格式:

:() {
:|:&
};
:

再易讀一點(diǎn):

test() {
test|test&
};
test

分析下:

:(){ } 定義一個函數(shù),函數(shù)名是冒號。

: 調(diào)用自身函數(shù)

| 管道符

: 再一次遞歸調(diào)用自身函數(shù)

:|: 表示每次調(diào)用函數(shù)":"的時候就會生成兩份拷貝。

& 放到后臺

; 分號是繼續(xù)執(zhí)行下一個命令,可以理解為換行。

: 最后一個冒號是調(diào)用函數(shù)。

因此不斷生成新進(jìn)程,直到系統(tǒng)資源崩潰,遞歸函數(shù)用的不多。

  1. 創(chuàng)建Apache軟件安裝函數(shù),給函數(shù)Apache_install傳遞參數(shù)1:

#!/bin/bash
#auto install LAMP 
#By author test.net
#Httpd define path variable
H_FILES=httpd-2.2.31.tar.bz2
H_FILES_DIR=httpd-2.2.31
H_URL=http://mirrors.cnnic.cn/apache/httpd/
H_PREFIX=/usr/local/apache2/
function Apache_install()
{
#Install httpd web server 
if [[ "$1" -eq "1" ]];then
	wget -c $H_URL/$H_FILES &&  tar -jxvf $H_FILES && cd $H_FILES_DIR &&./configure --prefix=$H_PREFIX 
	if [ $? -eq 0 ];then
		make && make install
		echo -e "\n\033[32m-----------------------------------------------\033[0m"
		echo -e "\033[32mThe $H_FILES_DIR Server Install Success !\033[0m"
	else
		echo -e "\033[32mThe $H_FILES_DIR Make or Make install ERROR,Please Check......"
		exit 0
	fi
fi
}
Apache_install 1
  1. 創(chuàng)建judge_ip判斷IP函數(shù):

#!/bin/bash
#By author test.net
judge_ip(){
        read -p "Please enter ip Address,example 192.168.0.11 ip": IPADDR
        echo $IPADDR|grep -v "[Aa-Zz]"|grep --color -E "([0-9]{1,3}\.){3}[0-9]{1,3}"
}
judge_ip
Shell 正則表達(dá)式

什么是正則表達(dá)式?

正則表達(dá)式在每種語言中都會有,功能就是匹配符合你預(yù)期要求的字符串。

為什么要學(xué)正則表達(dá)式?

在企業(yè)工作中,我們每天做的linux運(yùn)維工作中,時刻都會面對大量帶有字符串的文本配置、程序、命令輸出及日志文件等,而我們經(jīng)常會有迫切的需要,從大量的字符串內(nèi)容中查找符合工作需要的特定的字符串。這就要靠正則表達(dá)式。因此,可以說正則表達(dá)式就是為過濾字符的需求而生的! 例如:ifconfig的輸出取IP,例如:cat /var/log/messages輸出等

兩個注意事項:

  1. 正則表達(dá)式應(yīng)用非常廣泛,存在于各種語言中,例如:php、python、java等。但是我們今天講的linux系統(tǒng)運(yùn)維工作中的正則表達(dá)式,即linux正則表達(dá)式,最常用正則表達(dá)式的命令就是grep(egrep)、sed、awk,換句話說linux四劍客劍客要想工作的各高效,那一定離不開正則表達(dá)式配合的。

  2. 正則表達(dá)式和我們常用的通配符特殊字符是用本質(zhì)去別的,這一點(diǎn)要注意。通配符例子:ls .log**這里的就是通配符(表示所有),不是正則表達(dá)式

Shell 正則表達(dá)式分為兩種:

  • 基礎(chǔ)正則表達(dá)式:BRE(basic regular express)

  • 擴(kuò)展正則表達(dá)式:ERE(extend regular express),擴(kuò)展的表達(dá)式有+、?、|和()

下面是一些常用的正則表達(dá)式符號

正則表達(dá)式
描述

\
轉(zhuǎn)義符,將特殊字符進(jìn)行轉(zhuǎn)義,忽略其特殊意義

^
匹配行首,awk中,^則是匹配字符串的開始

$
匹配行尾,awk中,$則是匹配字符串的結(jié)尾

.
匹配除換行符\n之外的任意單個字符,awk則中可以

[]
匹配包含在[字符]之中的任意一個字符

[^ ]
匹配字符之外的任意一個字符

^[^]
匹配不是中括號內(nèi)任意一個字符開頭的行

[ - ]
匹配[]中指定范圍內(nèi)的任意一個字符,要寫成遞增

?
匹配之前的項1次或者0次

+
匹配之前的項1次或者多次

*
匹配之前的項0次或者多次

()
匹配表達(dá)式,創(chuàng)建一個用于匹配的子串

{ n }
匹配之前的項n次,n是可以為0的正整數(shù)

{n,}
之前的項至少需要匹配n次

{n,m}
指定之前的項至少匹配n次,最多匹配m次,n<=m

|
交替匹配|兩邊的任意一項

<
邊界符,匹配字符串開始

>
邊界符,匹配字符串結(jié)束

基本正則表達(dá)式實踐

接下來的測試文本如下:

[root@localhost ~]# cat test.log 
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges –notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges –emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty

%end...
=========================

以下實踐通過grep 命令增加正則表達(dá)式進(jìn)行匹配練習(xí)

  1. ^(尖角號)功能實踐

# 匹配首字母為%的行
[root@localhost ~]#  grep -n "^%" test.log 
# -n 參數(shù)是顯示匹配到的行號。

Shell企業(yè)編程基礎(chǔ)實戰(zhàn)

  1. $

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI