shell腳本編程

一、shell入門

Shell是操作系統的最外層,Shell可以合併編程語言以控制進程和文件,以及啓動和控制其它程序。shell 通過提示您輸入,向操作系統解釋該輸入,然後處理來自操作系統的任何結果輸出來管理您與操作系統之間的交互。簡單來說Shell就是一個用戶跟操作系統之間的一個命令解釋器。
Shell是用戶與Linux操作系統之間溝通的橋樑。用戶可以輸入命令執行,又可以利用 Shell腳本編程去運行。

在這裏插入圖片描述

Linux 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在日常工作中被廣泛使用,也是大多數Linux系統默認的Shell。接下來我們來寫一個簡單的shell腳本。(shell腳本一般文件名以.sh結尾,同時文件第一行定義該腳本爲shell腳本)
vi first_shell.sh

#!/bin/bash
#This is my First shell
echo  “Hello  World !

這就是我們的第一個腳本,是不是很簡單呢,註解如下:
#!/bin/bash:表示定義該腳本是一個shell腳本(固定格式)。
#This is my First shell:這裏的#號屬於註解,沒有任何的意義,SHELL不會解析它。
echo “Hello World !” :shell腳本主命令,我們執行這個腳本講看到: Hello World ! 信息;echo:輸出命令。
腳本編寫完畢,如何來執行呢,首先執行shell腳本需要執行權限,賦予執行權限:
chmod o+x first_shell.sh 然後./first_shell.sh執行即可;也可以直接使用命令執行: /bin/sh first_shell.sh,顯示效果一樣。

二、Shell編程之變量詳解

Shell編程語言是非類型的解釋型語言,不像C++/JAVA語言編程時需要事先聲明量,SHELL給一個變量賦值,實際上就是定義了變量,在Linux支持的所有shell中,都可以用賦值符號=爲變量賦值。
SHELL變量可分爲兩類:局部變量環境變量。局部變量只在創建它們的shell腳本中使用。而環境變量則可以在創建它們的shell及其派生出來的任意子進程中使用。有些變量是用戶創建的,其他的則是專用shell變量。
例如在腳本里面定義A=123 ,定義這樣一個變量,前面A就是變量名,後面123就是變量的值。
引用變量可以使用$A,把變量放在腳本里面會出現什麼樣的效果呢?如下:
vi test.sh

#!/bin/bash
#Author sgw 2020-02-18
A=123
echo  “Printf variables equal is $A

執行腳本:sh test.sh,結果將會顯示:

Printf variables equal is 123

SHELL常見的系統變量解析:

$0 當前程序的名稱(當前腳本的名稱)
$n 當前程序的第n個參數,n=1,2,…9
$* 當前程序的所有參數(不包括程序本身)
$# 當前程序的參數個數(不包括程序本身)
$? 命令或程序執行完後的狀態,一般返回0表示執行成功。(即判斷上一條命令是否正確執行完畢)
$UID 當前用戶的ID  輸出0,則表示ROOT用戶
$PWD 當前所在的目錄

測試$0$1$2的腳本
vi sh myshell.sh

#!/bin/bash
#by sgw 2020-02-18
echo $0
echo $1
echo $2

執行腳本:

# hello:第一個參數  sgw:第二個參數
sh myshell.sh hello sgw

輸出結果:

myshell.sh
hello
sgw

測試$?$*$#的腳本

#!/bin/bash
#by sgw 2020-02-18
echo  "the \$? is:$?"
echo  "the \$* is:$*"
echo  "the \$# is:$#"

其中,反斜槓\是轉移字符
執行該腳本

sh myshell.sh hello sgw

執行結果

the $? is:0
the $* is:hello sgw
the $# is:2

其中,$?判斷的是上一條命令是否執行成功,我們隨便在控制檯執行一個錯誤的命令,然後執行$?查看結果:
在這裏插入圖片描述
$?得到的結果不是0,說明上一條命令執行失敗了;

給輸出的內容加上顏色

#!/bin/bash
#by sgw 2020-02-18
echo -e "\033[32mplease select Menu follow:\033[1m"
echo "1:安裝apache服務器"
echo "2:安裝mysql服務器"
echo "3:安裝PHP服務器"
echo "4:配置LAMP WEB架構"

其中:-e "\033[32m\033[1m是爲了添加顏色
執行腳本

sh myshell.sh 

結果:
在這裏插入圖片描述

查看shell腳本有沒有語法錯誤

/bin/bash -n myshell.sh

如果執行該命令後沒有任何輸出,則表明腳本寫的沒問題
在這裏插入圖片描述

三、shell編程之if條件語句

在Linux Shell編程中,if、for、while、case等條件流程控制語句用的非常多,把這些學好,對提升腳本的功力有非常大的幫助。下面將逐個來講解具體的用法

If條件判斷語句

語法格式

if  (表達式)  #if ( Variable in Array )
語句1
else
語句2
fi

案例一:比較數字大小

#!/bin/bash
#by sgw 2020-02-19
NUM1=100
NUM2=200

if(($NUM1>$NUM2));then
  echo "this $NUM1 great $NUM2 !"
else 
  echo "this $NUM1 little $NUM2 !"
fi

if後有兩個括號的話,說明是用來比較大小的
執行腳本後的結果:

this 100 little 200 !

常見的邏輯運算符

-f	 判斷文件是否存在 eg: if [ -f filename ]
-d	 判斷目錄是否存在 eg: if [ -d dir     ]
-eq	 等於 應用於:整型比較
-ne	 不等於 應用於:整型比較
-lt	 小於 應用於:整型比較
-gt	 大於 應用於:整型比較
-le	 小於或等於 應用於:整型比較
-ge	 大於或等於 應用於:整型比較
-a	 雙方都成立(and) 邏輯表達式 –a 邏輯表達式
-o	 單方成立(or) 邏輯表達式 –o 邏輯表達式
-z	 空字符串

案例二、判斷目錄是否存在,不存在則新建(注意,中括號之間必須要有空格)

#!/bin/sh
#judge dir exist
if  [ ! -d  /data/20200219 ];then 
    mkdir  -p /data/20200219 
else
	echo  “This DIR is exist,Please exit..fi

案例三:判斷文件是否存在

#!/bin/bash
#by sgw 2020-02-19
FILES=/usr/local/test/test.txt

if [ ! -f $FILES ];then
  echo "OK" >> $FILES
else
  echo "-----------------"
  cat $FILES
fi

其中echo "OK" >> $FILES表示將"OK"寫入/usr/local/test/test.txt文件裏,一個大於號表示覆蓋原來的內容,兩個大於號表示在原來的內容裏繼續追加;

案例三、多條件判斷

#!/bin/sh
scores=80
if  [[ $scores -gt 85 ]]; then
    echo "very good!";
elif [[ $scores -gt 75 ]]; then
    echo "good!";
elif [[ $scores -gt 60 ]]; then
    echo "pass!";
else
    echo "no pass!"
fi

上邊的分數是寫死的,下邊根據我們輸入不同的分數,打印不同的信息

#!/bin/bash
#by sgw 2020-02-19
scores=$1

if [ -z $scores ];then
    echo "usage: {$0 60|80}"
    exit
fi
if  [[ $scores -gt 85 ]]; then
    echo "very good!";
elif [[ $scores -gt 75 ]]; then
    echo "good!";
elif [[ $scores -gt 60 ]]; then
    echo "pass!";
else
    echo "no pass!"
fi

如果執行腳本時不加參數的話,會有提示

在這裏插入圖片描述
加上參數後再執行腳本

在這裏插入圖片描述

mysql備份腳本模板

#!/bin/sh 
#auto backup mysql 
#sgw 2020-02-20 
#Define PATH定義變量  腳本存放目錄 注意:日期使用反引號括起來(Esc鍵下邊的鍵),反引號括起來表示將反引號裏的內容作爲命令來執行
BAKDIR=/data/backup/mysql/`date +%Y-%m-%d`
# mysql庫名
MYSQLDB=webapp
# 密碼
MYSQLPW=backup
# 用戶名
MYSQLUSR=backup
#must use root user run scripts 必須使用root用戶運行(0指root用戶),$UID爲系統變量
if	
   [ $UID -ne 0 ];then
   echo "This script must use the root user ! ! !" 
   sleep 2
   exit 0
fi
#Define DIR and mkdir DIR 判斷目錄是否存在,不存在則新建
if
   [ ! -d $BAKDIR ];then
   mkdir -p $BAKDIR
else
   echo "This is $BAKDIR exists...." 
fi
#Use mysqldump backup mysql 使用mysqldump備份數據庫
/usr/bin/mysqldump -u$MYSQLUSR -p$MYSQLPW -d $MYSQLDB >$BAKDIR/webapp_db.sql
echo "The mysql backup successfully "

四、shell編程之LAMP一鍵安裝腳本

LAMP指的是在linux下安裝APACHE、MYSQL、PHP

#!/bin/bash
#auto install LAMP 
#by sgw 2020-02-21

#Httpd(apache) define path variable
H_FILES=httpd-2.2.27.tar.bz2
H_FILES_DIR=httpd-2.2.27
H_URL=http://mirrors.cnnic.cn/apache/httpd/
H_PREFIX=/usr/local/apache2/

#MySQL define path variable
M_FILES=mysql-5.5.20.tar.gz
M_FILES_DIR=mysql-5.5.20
M_URL=http://down1.chinaunix.net/distfiles/
M_PREFIX=/usr/local/mysql/


#PHP define path variable
P_FILES=php-5.3.28.tar.bz2
P_FILES_DIR=php-5.3.28
P_URL=http://mirrors.sohu.com/php/
P_PREFIX=/usr/local/php5/

# 如果不輸入參數的話,就強制退出,什麼也安裝
if [ -z "$1" ];then

	echo -e "\033[36mPlease Select Install Menu follow:\033[0m"
	echo -e "\033[32m1)編譯安裝Apache服務器\033[1m"
	echo "2)編譯安裝MySQL服務器"
	echo "3)編譯安裝PHP服務器"
	echo "4)配置index.php並啓動LAMP服務"
	echo -e "\033[31mUsage: { /bin/sh $0 1|2|3|4|help}\033[0m"
	exit
fi

# 如果用戶輸入的是1,則安裝apache
if [[ "$1" -eq "1" ]];then
	# bz結尾的壓縮包,需要使用jxvf命令來解壓; &&表示前邊的命令執行成功後,再執行後邊的命令。封號指的是不管前邊執行成功與否,都會執行後邊的命令
	# .configure是預編譯
	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 "\033[32mThe $H_FILES_DIR Server Install Sucessfully!\033[0m"
	else
		echo -e "\033[32mThe $H_FILES_DIR Server Install Failed,Please check。。。!\033[0m"
		exit
	fi
fi

# 如果用戶輸入的是2,則安裝mysql
if [[ "$1" -eq "2" ]];then
        wget -c $M_URL/$M_FILES &&  tar -xzvf $M_FILES && cd $M_FILES_DIR &&yum install cmake -y ;cmake . -DCMAKE_INSTALL_PREFIX=$M_PREFIX \
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
-DMYSQL_DATADIR=/data/mysql \
-DSYSCONFDIR=/etc \
-DMYSQL_USER=mysql \
-DMYSQL_TCP_PORT=3306 \
-DWITH_XTRADB_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_EXTRA_CHARSETS=1 \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DEXTRA_CHARSETS=all \
-DWITH_BIG_TABLES=1 \
-DWITH_DEBUG=0
make && make install

/bin/cp support-files/my-small.cnf /etc/my.conf
/bin/cp support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on

        if [ $? -eq 0 ];then
                make && make install
                echo -e "\n\033[32m-----------------------------------------------\033[0m"
                echo -e "\033[32mThe $M_FILES_DIR Server Install Success !\033[0m"
        else
                echo -e "\033[32mThe $M_FILES_DIR Make or Make install ERROR,Please Check......"
                exit 0
        fi
fi

# 如果用戶輸入的是3,則安裝php
if [[ "$1" -eq "3" ]];then

        wget -c $P_URL/$P_FILES &&  tar -jxvf $P_FILES && cd $P_FILES_DIR &&./configure --prefix=$P_PREFIX --with-config-file-path=$P_PREFIX/etc --with-mysql=$M_PREFIX --with-apxs2=$H_PREFIX/bin/apxs
        if [ $? -eq 0 ];then
                make ZEND_EXTRA_LIBS='-liconv' && make install
                echo -e "\n\033[32m-----------------------------------------------\033[0m"
                echo -e "\033[32mThe $P_FILES_DIR Server Install Success !\033[0m"
        else
                echo -e "\033[32mThe $P_FILES_DIR Make or Make install ERROR,Please Check......"
                exit 0
        fi
fi

# 用戶輸入4的話,做一個整體的配置(不理解的話先放過,後邊內容會講解)
if [[ "$1" -eq "4" ]];then

	sed -i '/DirectoryIndex/s/index.html/index.php index.html/g' $H_PREFIX/conf/httpd.conf 
	$H_PREFIX/bin/apachectl restart	
	echo "AddType     application/x-httpd-php .php" >>$H_PREFIX/conf/httpd.conf
	IP=`ifconfig eth1|grep "Bcast"|awk '{print $2}'|cut -d: -f2`
	echo "You can access http://$IP/"

cat >$H_PREFIX/htdocs/index.php <<EOF
<?php
phpinfo();
?>
EOF
fi

五、for循環

語法:

For 變量 in 字符串
do
	語句1
done

案例一、循環打印1—15之間的數字

linux裏的seq命令,會循環打印數字,如下:
在這裏插入圖片描述

腳本如下:

#!/bin/bash
#by sgw 2020-02-21
for i in `seq 1 15`
do
        echo "The Number is $i"
done

運行結果:
在這裏插入圖片描述

案例二、求和1-100的值

linux裏expr命令用於求和
在這裏插入圖片描述
腳本:

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

案例三、找到相關log,然後批量打包

#!/bin/sh
for   i   in  `find /var/log  -name “*.log”`
do
	tar –czf  2020log.tgz $i
done

案例四、遠程批量傳輸文件

#!/bin/bash
#auto scp files for client
#by authors sgw 2020
for i in `seq 100 200`
do
        scp -r /tmp/test.txt [email protected].$i:/data/webapps/www
Done

案例五、遠程主機批量執行命令

#!/bin/bash
#auto scp files for client
#by authors sgw 2020
for i in `seq 100 200`
do
       ssh -l  root 192.168.1.$i ‘ls /tmp’
done

六、while循環

語法:

while 條件語句

do

	語句1

done

案例一、while條件判斷數字

#!/bin/sh
i=1;
while [[ $i -lt 10 ]];
do
    echo $i;
    ((i++));
done;

linux裏的read命令:

read a

回車後輸入一個值,比如輸入123

123

上邊的命令就是起了一個變量a,並賦值爲123

查看變量a的值:

echo $a

在這裏插入圖片描述
定義變量並且加上提示語

# 定義變量,變量名稱爲input
read -p "Please input number:" input

回車後

# 在後邊輸入123
Please input number:123

查看變量input的值

echo $input

在這裏插入圖片描述
案例二、while逐行讀取某個文件裏的內容

#!/bin/sh
# line是變量名
while read line
do
    echo  $line;
# 讀取 /etc/hosts 文件
done  < /etc/hosts

七、Until循環

語法:

until 條件	
do
	action
done

直到滿足條件,才退出。否則執行action。

案例一、條件判斷數字

#!/bin/sh
a=10;
until [[ $a -lt 0 ]];do
	echo $a;
	((a--));
done;	

八、Case語句

語法:

case $arg in  
    pattern1)
    語句1 
    ;;  
    pattern2)
    語句2
    ;;  
    *)
    語句3
    ;;  
esac

案例一、創建選擇參數腳本

#!/bin/sh
case $1 in

        monitor_log)
        monitor_log
        ;;
        archive_log)
        archive_log
        ;;

        *          )
        echo "Usage:{$0 monitor_log | archive_log |help }"
        ;;
esac

上邊的語法裏,*代表輸入其他參數時,執行*下邊的邏輯

九、select選擇語句

Select一般用於選擇菜單的創建,可以配合PS3來做菜單的打印輸出信息。(PS3用來打印信息)

案例一:

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

in後邊是可以選擇的參數
運行結果:
在這裏插入圖片描述

十、Shell編程函數講解

shell允許將一組命令集或語句形成一個可用塊,這些塊稱爲shell函數,定義函數的格式:

function name (){
        command1
        ........
}
name 

調用函數時,直接執行函數名name即可

案例一、apache安裝函數

#!/bin/bash
#auto install LAMP 
#by sgw 2020-02-22
#Httpd define path variable
H_FILES=httpd-2.2.27.tar.bz2
H_FILES_DIR=httpd-2.2.27
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

十一、Shell數組編程

數組,就是相同數據類型的元素按一定順序排列的集合,就是把有限個類型相同的變量用一個名字命名,然後用編號區分他們的變量的集合,這個名字成爲數組名,編號成爲下標。
在這裏插入圖片描述

今天這裏我們來探討一維數組的定義、統計、引用和刪除等操作。

定義一個一維數組
A=( test1 test2 test3 ) ,定義數組一般以括號的方式來定義,數組的值可以隨機定義。

引用數組
echo ${A[0]},代表引用第一個數組變量,結果會顯示test1,數組引用從0開始,代表第一個數組,依次類推。
echo ${A[1]},代表引用第二個數組變量,結果會顯示test2,數組引用也是從0開始計算的。
如何顯示該數組所有參數呢?echo ${A[@]} 將顯示所有參數test1 test2 test3 。
如何顯示該數組參數個數呢?echo ${#A[@]} 將顯示該數組的參數個數3。
如果替換某個數組呢?例如替換第二個test2數組爲test5:echo ${A[@]/test2/test5}
如何刪除一個數組呢?例如刪除test3數組命令爲:unset A[2] ;echo ${A[@]}查看效果。

數組先講到這裏,具體使用的話,後邊後結合案例一起講解

十二、Shell編程之sed命令

sed命令
sed命令與vi命令類似,但是sed命令不需要打開文件後修改,只需要在文件外執行命令即可;
案例一、把test.txt文件裏面的192字符全部替換爲10

# -i:插入/修改的意思,s代表文件裏的全部
sed -i 's/192/10/g' test.txt  

案例二、在文件裏的指定位置添加一行指定內容,如:在sgw後一行添加test

# a表示下一行
sed -i '/sgw/a bbb' test.txt

在這裏插入圖片描述
如果在sgw前添加bbb的話,把上邊命令的a改爲i即可

sed -i '/sgw/i bbb' test.txt

案例三、將文件裏指定內容所在行信息打印出來
test.txt文件內容如下:

my name is sgw haha
my birthday is 0219
and my home is sx

將sgw所在的行信息打印出來

# p代表print打印
sed -n '/sgw/p' test.txt 

在這裏插入圖片描述
案例四:
打印文件裏的第一行內容:

sed -n '1p' test.txt

打印文件裏的第一,二行內容:

sed -n '1,2p' test.txt

打印文件裏的第一至第三行內容:

sed -n '1,3p' test.txt

在這裏插入圖片描述

十三、Shell編程之grep、awk、find命令

13.1 grep命令

匹配文件裏以某字符串開頭的內容所在行的信息
test.txt內容如下:

my name is sgw haha
my birthday is 0219
and my home is sx

案例一、匹配以m開頭的內容

# ^是正則表達式,數字6所在的鍵
grep "^m" test.txt

在這裏插入圖片描述
案例二、匹配以haha結尾的內容

grep "haha$" test.txt

在這裏插入圖片描述

案例三、匹配數字0-9之間的內容(即只要是數字就顯示出來)

grep "[0-9]" test.txt

在這裏插入圖片描述

案例四、匹配字母a-z之間的內容(即只要是字母就顯示出來)

grep "[a-z]" test.txt

在這裏插入圖片描述
案例五、匹配字母a-z開頭的內容(即只要是字母就顯示出來)

grep "^[a-z]" test.txt

在這裏插入圖片描述
案例六、匹配sgw與0219這兩個內容

egrep "sgw|0219" test.txt 

在這裏插入圖片描述

13.2 awk命令

案例一、打印第四列(默認以空格分開列數)

原文件內容:
在這裏插入圖片描述

# $後加的是要打印的第幾列,$後加NF代表打印最後一列
cat test.txt |awk '{print $4}'

在這裏插入圖片描述
案例二、以冒號爲分隔單位,打印第一列

原文件(在之前的基礎上加了冒號):

my name: is sgw haha
my birthday: is 0219
and my home: is sx

打印第一列:

cat test.txt |awk -F: '{print $1}'

其中,-F:代表把冒號作爲分隔符(F是format:自定義分隔符)
在這裏插入圖片描述

13.3 find命令

find是查找文件的命令,find後加路徑以及文件名,就可以查找文件了

不知道文件的路徑,則從根路徑查找

從根目錄裏開始找

# 從根路徑開始查找test.txt文件
find / -name "test.txt"

從當前目錄以及子目錄裏開始找

find . -name "test.txt"

只在當前目錄查找(只找第一級目錄)

find . -maxdepth 1 -name "test.txt"

查找指定類型的文件

# 查找當前目錄下的文件,且文件類型是txt結尾的  f代表文件
find . -maxdepth 1 type f -name "*.txt"

查找指定日期之前修改過的文件

# 30天之前改過的txt文件
find . -maxdepth 1 type f -name "*.txt" -mtime +30

# 1天以內改過的txt文件
find . -maxdepth 1 type f -name "*.txt" -mtime -1

查找到之後將文件刪除

exec:將exec前的結果作爲參數放在後邊的{}裏,並執行rm -rf刪除命令
find . -maxdepth 1 type f -name "*.txt" -mtime -1 -exec rm -rf {} \;

查找到之後將文件複製到指定目錄

# 查找到之後將文件複製到/usr/loca目錄下
find . -maxdepth 1 type f -name "*.txt" -mtime -1 -exec cp {} /usr/local \;

查找當前目錄下大於20M的文件

# 查找當前目錄以及子目錄下大於20M的文件與文件夾
find . -size +20M

# 查找當前目錄下大於20M的文件
find . -maxdepth 1 -size +20M -type f

查找到30天之前的文件並刪除

find . -mtime +30 -exect rm -f {} \;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章