shell腳本編程

shell是什麼nginx

shell是一種腳本語言
可使用邏輯判斷、循環等語法
能夠自定義函數
shell是系統命令的集合
shell腳本能夠實現自動化運維,能大大增長咱們的運維效率

shell腳本結構和執行shell

開頭須要加#!/bin/bash
以#開頭的行做爲解釋說明
腳本的名字以.sh結尾,用於區分這是一個shell腳本
執行方法有兩種
chmod +x 1.sh; ./1.sh
bash 1.sh
查看腳本執行過程 bash -x 1.sh
查看腳本是否語法錯誤  bash -n 1.sh

測試:vim

[root@wangzb02 ~]# vim 1.sh 建立1.sh腳本,增長內容
#!/bin/bash
touch /tmp/1.txt
chmod 600 /tmp/1.txt
mv /tmp/1.txt /tmp/2.txt

[root@wangzb02 ~]# ./1.sh
-bash: ./1.sh: 權限不夠

[root@wangzb02 ~]# chmod 755 1.sh 
[root@wangzb02 ~]# bash 1.sh 
[root@wangzb02 ~]# bash -x 1.sh 
+ touch /tmp/1.txt
+ chmod 600 /tmp/1.txt
+ mv /tmp/1.txt /tmp/2.txt

補充:數組

以樹形查看服務
[root@wangzb02 ~]# yum install -y psmisc
[root@wangzb02 ~]# pstree  //能夠看到
systemd─┬─NetworkManager─┬─dhclient
    │                └─2*[{NetworkManager}]
    ├─VGAuthService
    ├─agetty
    ├─auditd───{auditd}
    ├─chronyd
    ├─crond
    ├─dbus-daemon
    ├─irqbalance
    ├─master─┬─pickup
    │        └─qmgr
    ├─nginx───nginx
    ├─polkitd───6*[{polkitd}]
    ├─rsyslogd───2*[{rsyslogd}]
    ├─sshd───sshd───bash───pstree
    ├─systemd-journal
    ├─systemd-logind
    ├─systemd-udevd
    ├─tuned───4*[{tuned}]
    ├─vmtoolsd───{vmtoolsd}
    └─zabbix_agentd───5*[zabbix_agentd]

date命令bash

date  +%Y-%m-%d, date +%y-%m-%d 年月日
date  +%H:%M:%S = date +%T 時間
date +%s  時間戳
date -d @1504620492
date -d "+1day"  一天後
date -d "-1 day"  一天前
date -d "-1 month" 一月前
date -d "-1 min"  一分鐘前
date +%w, date +%W 星期

測試:運維

[root@wangzb02 ~]# date
2019年 03月 06日 星期三 22:45:06 CST
[root@wangzb02 ~]# date  +%Y-%m-%d
2019-03-06
[root@wangzb02 ~]# date +%y-%m-%d
19-03-06
[root@wangzb02 ~]# date  +%H:%M:%S
22:43:43
[root@wangzb02 ~]# date +%T
22:43:52
[root@wangzb02 ~]# date +%s
1551883442
[root@wangzb02 ~]# date -d @1504620492
2017年 09月 05日 星期二 22:08:12 CST
[root@wangzb02 ~]# date -d "+1day" 
2019年 03月 07日 星期四 22:44:24 CST
[root@wangzb02 ~]# date -d "-1 day"
2019年 03月 05日 星期二 22:44:34 CST
[root@wangzb02 ~]# date -d "-1 month" 
2019年 02月 06日 星期三 22:44:45 CST
[root@wangzb02 ~]# date +%w
3
[root@wangzb02 ~]# date +%W
09
[root@wangzb02 ~]# date -d @123123123
1973年 11月 26日 星期一 08:52:03 CST
[root@wangzb02 ~]# date -d "-1hour"
2019年 03月 06日 星期三 21:50:30 CST

shell腳本中的變量ssh

當腳本中使用某個字符串較頻繁而且字符串長度很長時就應該使用變量代替
使用條件語句時,常使用變量    if [ $a -gt 1 ]; then ... ; fi
引用某個命令的結果時,用變量替代   n=`wc -l 1.txt`
寫和用戶交互的腳本時,變量也是必不可少的  
read -p "Input a number: " n; echo $n   若是沒寫這個n,能夠直接使用$REPLY

[root@wangzb01 ~]# a=`date +%w`
[root@wangzb01 ~]# echo $a
4
[root@wangzb01 ~]# a=$(date +%w)
[root@wangzb01 ~]# echo $a
4
[root@wangzb01 ~]# read -p "請輸入一個數字n:" n
請輸入一個數字n:10
[root@wangzb01 ~]# echo $n
10
[root@wangzb01 ~]# read -p "請輸入一個數字n:" 
請輸入一個數字n:2312
[root@wangzb01 ~]# echo $REPLY
2312

內置變量 $0, $1, $2…    $0表示腳本自己,$1 第一個參數,$2 第二個 ....       $#表示參數個數

[root@wangzb01 ~]# vim 1.sh  //增長內容:
#!/bin/bash
echo "\$1=$1"
echo "第二個參數是$2"
echo "第三個參數是$3"
echo "本腳本一共有$#個參數"
echo "\$0參數是$0"

[root@wangzb01 ~]# sh 1.sh aa bb cc dd ee
$1=aa
第二個參數是bb
第三個參數是cc
本腳本一共有5個參數
$0參數是1.sh

[root@wangzb01 ~]# sh /root/1.sh aa bb cc dd ee
$1=aa
第二個參數是bb
第三個參數是cc
本腳本一共有5個參數
$0參數是/root/1.sh

數學運算a=1;b=2; c=$(($a+$b))或者$[$a+$b]

說明:函數

\ :脫義字符
$# :shell的內置變量,表示參數個數
$0 :表示shell腳本自己
$REPLY : shell內置變量

shell中的邏輯判斷post

格式1:if 條件 ; then 語句; fi
格式2:if 條件; then 語句; else 語句; fi
格式3:if …; then … ;elif …; then …; else …; fi
邏輯判斷表達式:if [ $a -gt $b ]; if [ $a -lt 5 ]; if [ $b -eq 10 ]等 -gt (>); -lt(<); -ge(>=); -le(<=);-eq(==); -ne(!=) 注意處處都是空格
可使用 && || 結合多個條件
if [ $a -gt 5 ] && [ $a -lt 10 ]; then
if [ $b -gt 5 ] || [ $b -lt 3 ]; then

if [ $a -gt 5 ] && [ $a -lt 10 ] == [ $a -gt 5 -a $a -lt 10 ]
if [ $a -gt 5 ] || [ $a -lt 10 ] == [ $a -gt 5 -o $a -lt 10 ]

if 判斷文件、目錄屬性測試

[ -f file ]判斷是不是普通文件,且存在
[ -d file ] 判斷是不是目錄,且存在
[ -e file ] 判斷文件或目錄是否存在
[ -r file ] 判斷文件是否可讀
[ -w file ] 判斷文件是否可寫
[ -x file ] 判斷文件是否可執行

注:root用戶對文件的讀寫比較特殊,即便一個文件沒有給root用戶讀或者寫的權限,root用戶照樣能夠讀或者寫

if判斷的一些特殊用法

if [ -z "$a" ]  這個表示當變量a的值爲空時會怎麼樣
if [ -n "$a" ] 表示當變量a的值不爲空
if grep -q '123' 1.txt; then  表示若是1.txt中含有'123'的行時會怎麼樣
if [ ! -e file ]; then 表示文件不存在時會怎麼樣
if (($a<1)); then …等同於 if [ $a -lt 1 ]; then… 
[ ] 中不能使用<,>,==,!=,>=,<=這樣的符號

shell中的case判斷

格式

case  變量名 in 
        value1)    
              command  
	      ;;
        value2)      
              command  
              ;; 
        *)  
              commond 
              ;;     
     esac

	在case程序中,能夠在條件中使用|,表示或的意思, 好比   
     2|3)     
	command
	;;

案例:

[root@wangzb01 shelltest]# vim case1.sh //增長內容
#!/bin/bash
read -p "Please input a number: " n
if [ -z "$n" ]
then
	echo "Please input a number."
	exit 1
fi

n1=`echo $n|sed 's/[0-9]//g'`
if [ -n "$n1" ]
then
 echo "Please input a number."
 exit 1
fi

if [ $n -lt 60 ] && [ $n -ge 0 ]
then
	tag=1
elif [ $n -ge 60 ] && [ $n -lt 80 ]
then
	tag=2
elif [ $n -ge 80 ]  && [ $n -lt 90 ]
then
	tag=3
elif [ $n -ge 90 ] && [ $n -le 100 ]
then
	tag=4
else 
	tag=0
fi

case $tag in
	1)
	echo "not ok"
		;;
	2)
		echo "ok"
		;;
	3)
		echo "ook"
		;;
	4)
		echo "oook"
		;;
	*)
		echo "The number range is 0-100."
		;; 
esac

輸出結果:

[root@wangzb01 shelltest]# sh -x case1.sh 
+ read -p 'Please input a number: ' n
Please input a number: 25
+ '[' -z 25 ']'
++ echo 25
++ sed 's/[0-9]//g'
+ n1=
+ '[' -n '' ']'
+ '[' 25 -lt 60 ']'
+ '[' 25 -ge 0 ']'
+ tag=1
+ case $tag in
+ echo 'not ok'
not ok
[root@wangzb01 shelltest]# sh -x case1.sh 
+ read -p 'Please input a number: ' n
Please input a number: 500
+ '[' -z 500 ']'
++ sed 's/[0-9]//g'
++ echo 500
+ n1=
+ '[' -n '' ']'
+ '[' 500 -lt 60 ']'
+ '[' 500 -ge 60 ']'
+ '[' 500 -lt 80 ']'

for循環

語法:for 變量名 in 條件; do …; done
案例1
#!/bin/bash
sum=0
for i in `seq 1 100`
do
	sum=$[$sum+$i]
	echo $i
done
echo $sum


文件列表循環

#!/bin/bash

cd /etc/
for a in `ls /etc/`
do
	if [ -d $a ]
	then
	ls -d $a
	fi
done

while循環

語法 while 條件; do … ; done
案例1

#!/bin/bash
while :  //冒號 : 表示死循環的意思,或者1,或者 true都是死循環
do
	load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1`
	if [ $load -gt 10 ]
	then
		top|mail -s "load is high: $load" asldkfls@11.com
	fi
	sleep 5 //#休眠5秒,由於檢查系統負載,不須要一直去檢查,過一會再看
done

執行結果:

[root@wangzb01 shelltest]# sh -x while1.sh 
+ :
++ w
++ head -1
++ awk -F 'load average: ' '{print $2}'
++ cut -d. -f1
+ load=0
+ '[' 0 -gt 10 ']'
+ sleep 5
+ :
++ w
++ cut -d. -f1
++ awk -F 'load average: ' '{print $2}'
++ head -1
+ load=0
+ '[' 0 -gt 10 ']'
+ sleep 5


案例2
[root@wangzb01 shelltest]# vim while2.sh
#!/bin/bash
while :
do
	read -p "Please input a number: " n
	if [ -z "$n" ]
	then
	echo "you need input sth."
	continue   //continue 從新回到循環
	fi
	n1=`echo $n|sed 's/[0-9]//g'`
	if [ -n "$n1" ]
	then
	echo "you just only input numbers."
		continue
	fi
	break   //break 退出循環
done
echo $n

執行腳本:

[root@wangzb01 shelltest]# sh -x while2.sh 
+ :
+ read -p 'Please input a number: ' n
Please input a number: abc
+ '[' -z abc ']'
++ echo abc
++ sed 's/[0-9]//g'
+ n1=abc
+ '[' -n abc ']'
+ echo 'you just only input numbers.'
you just only input numbers.
+ continue
+ :
+ read -p 'Please input a number: ' n
Please input a number: ad1
+ '[' -z ad1 ']'
++ echo ad1
++ sed 's/[0-9]//g'
+ n1=ad
+ '[' -n ad ']'
+ echo 'you just only input numbers.'
you just only input numbers.
+ continue
+ :
+ read -p 'Please input a number: ' n
Please input a number: 11111
+ '[' -z 11111 ']'
++ echo 11111
++ sed 's/[0-9]//g'
+ n1=
+ '[' -n '' ']'
+ break
+ echo 11111
11111

[root@wangzb01 shelltest]# sh  while2.sh 
Please input a number: abc
you just only input numbers.
Please input a number: abc123
you just only input numbers.
Please input a number: 111111
111111

break跳出循環

#!/bin/bash
for i in `seq 1 5`
do
	echo $i
	if [ $i == 3 ]
	then
		break
	fi
	echo $i
done
echo aaaaaaa

執行結果:

[root@wangzb01 shelltest]# sh break1.sh 
1
1
2
2
3
aaaaaaa
[root@wangzb01 shelltest]# sh -x break1.sh 
++ seq 1 5
+ for i in '`seq 1 5`'
+ echo 1
1
+ '[' 1 == 3 ']'
+ echo 1
1
+ for i in '`seq 1 5`'
+ echo 2
2
+ '[' 2 == 3 ']'
+ echo 2
2
+ for i in '`seq 1 5`'
+ echo 3
3
+ '[' 3 == 3 ']'
+ break
+ echo aaaaaaa
aaaaaaa

continue結束本次循環

忽略continue之下的代碼,直接進行下一次循環
[root@wangzb01 shelltest]# vim continue.sh
#!/bin/bash
for i in `seq 1 5`
do
	echo $i
	if [ $i == 3 ]
	then
	continue
	fi
	echo $i
done
echo $i

[root@wangzb01 shelltest]# sh continue.sh 
1
1
2
2
3
4
4
5
5
5

exit直接退出腳本

#!/bin/bash
for i in `seq 1 5`
do
	echo $i
	if [ $i == 3 ]
	then
	exit
	fi
	echo $i
done
echo aaaaaaa

執行結果:

[root@wangzb01 shelltest]# sh -x exit1.sh 
++ seq 1 5
+ for i in '`seq 1 5`'
+ echo 1
1
+ '[' 1 == 3 ']'
+ echo 1
1
+ for i in '`seq 1 5`'
+ echo 2
2
+ '[' 2 == 3 ']'
+ echo 2
2
+ for i in '`seq 1 5`'
+ echo 3
3
+ '[' 3 == 3 ']'
+ exit

[root@wangzb01 shelltest]# cp /etc/passwd ./test
[root@wangzb01 shelltest]# for line in `cat test`;do echo $line ; echo "#####"; done
root:x:0:0:root:/root:/bin/bash
#####
bin:x:1:1:bin:/bin:/sbin/nologin
#####
daemon:x:2:2:daemon:/sbin:/sbin/nologin
#####
adm:x:3:4:adm:/var/adm:/sbin/nologin
#####
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
#####
sync:x:5:0:sync:/sbin:/bin/sync
#####
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
#####
halt:x:7:0:halt:/sbin:/sbin/halt
#####
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
#####
operator:x:11:0:operator:/root:/sbin/nologin
#####
games:x:12:100:games:/usr/games:/sbin/nologin
#####
ftp:x:14:50:FTP
#####
User:/var/ftp:/sbin/nologin
#####
nobody:x:99:99:Nobody:/:/sbin/nologin
#####
systemd-network:x:192:192:systemd
#####
Network

採用for循環到後面輸出的行出現問題,緣由是行中間有空格。下面可使用while循環的方式來實現,空格就不會有影響了

[root@wangzb01 shelltest]# cat test | while read line; do echo $line ; echo "######"; doneroot:x:0:0:root:/root:/bin/bash
######
bin:x:1:1:bin:/bin:/sbin/nologin
######
daemon:x:2:2:daemon:/sbin:/sbin/nologin
######
adm:x:3:4:adm:/var/adm:/sbin/nologin
######
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
######
sync:x:5:0:sync:/sbin:/bin/sync
######
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
######
halt:x:7:0:halt:/sbin:/sbin/halt
######
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
######
operator:x:11:0:operator:/root:/sbin/nologin
######
games:x:12:100:games:/usr/games:/sbin/nologin
######
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
######
nobody:x:99:99:Nobody:/:/sbin/nologin
######
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
######
dbus:x:81:81:System message bus:/:/sbin/nologin
######
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
######
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
######
postfix:x:89:89::/var/spool/postfix:/sbin/nologin

shell腳本中的函數

函數就是把一段代碼整理到了一個小單元中,並給這個小單元起一個名字,當用到這段代碼時直接調用這個小單元的名字便可。
格式: 
function f_name() 
{ 
		command
}

函數必需要放在最前面
示例1 
#!/bin/bash
input() {
	echo $1 $2 $# $0
}
input 1 a b

執行結果:

[root@wangzb01 shelltest]# sh function01.sh 
1 a 3 function01.sh
[root@wangzb01 shelltest]# sh -x function01.sh 
+ input 1 a b
+ echo 1 a 3 function01.sh
1 a 3 function01.sh

示例2 
#!/bin/bash
sum() {
	s=$[$1+$2]
	echo $s
}
sum 1 2

執行結果:

[root@wangzb01 shelltest]# sh function02.sh 
3
[root@wangzb01 shelltest]# sh -x function02.sh 
+ sum 1 2
+ s=3
+ echo 3
3


示例3 
#!/bin/bash
ip() 
{
	ifconfig |grep -A1 "$1: " |tail -1 |awk '{print $2}'
}
read -p "Please input the eth name: " e
myip=`ip $e`
echo "$e address is $myip"

執行結果:

[root@wangzb01 shelltest]# sh function03.sh 
Please input the eth name: ens33
ens33 address is 192.168.153.133
[root@wangzb01 shelltest]# sh -x function03.sh 
+ read -p 'Please input the eth name: ' e
Please input the eth name: ens33
++ ip ens33
++ ifconfig
++ tail -1
++ grep -A1 'ens33: '
++ awk '{print $2}'
+ myip=192.168.153.133
+ echo 'ens33 address is 192.168.153.133'
ens33 address is 192.168.153.133

shell中的數組

定義數組 a=(1 2 3 4 5); echo ${a[@]}
echo ${#a[@]} 獲取數組的元素個數 
echo ${a[2]} 讀取第三個元素,數組從0開始
echo ${a[*]} 等同於 ${a[@]}  顯示整個數組

案例測試:

[root@wangzb01 shelltest]# a=(1 2 a b c)
[root@wangzb01 shelltest]# echo ${a[@]}
1 2 a b c
[root@wangzb01 shelltest]# echo ${a[1]}
2
[root@wangzb01 shelltest]# echo ${a[2]}
a
[root@wangzb01 shelltest]# echo ${#a[@]}
5
[root@wangzb01 shelltest]# echo ${a[*]}
1 2 a b c


數組賦值
a[1]=100; echo ${a[@]}
a[5]=2; echo ${a[@]} 若是下標不存在則會自動添加一個元素

案例測試:

[root@wangzb01 shelltest]# a[5]=aaa
[root@wangzb01 shelltest]# a[8]=bbb
[root@wangzb01 shelltest]# echo ${a[*]}  //此處a[5]、a[6]、a[7]沒有賦值,是空值
1 2 a b c aaa bbb
[root@wangzb01 shelltest]# echo ${#a[*]}
7

數組的刪除
unset a; unset a[1]

案例測試:

[root@wangzb01 shelltest]# unset a[8]
[root@wangzb01 shelltest]# echo ${a[@]}
1 2 a b c aaa
[root@wangzb01 shelltest]# echo ${#a[@]}
6

數組分片
a=(`seq 1 5`)
echo ${a[@]:0:3} 從第一個元素開始,截取3個
echo ${a[@]:1:4} 從第二個元素開始,截取4個
echo ${a[@]:0-3:2} 從倒數第3個元素開始,截取2個

案例測試:

[root@wangzb01 shelltest]# echo ${a[@]}  //查詢全部
1 2 a b c aaa
[root@wangzb01 shelltest]# echo ${a[@]:0:2}   //從第一個參數開始,取兩個參數
1 2
[root@wangzb01 shelltest]# echo ${a[@]:1:5}   //從第二個參數開始,取5個參數
2 a b c aaa
[root@wangzb01 shelltest]# echo ${a[@]:0-3:3}  //從倒數第三個參數開始,取三個參數
b c aaa

數組替換
echo ${a[@]/3/100}
a=(${a[@]/3/100})

案例測試:

[root@wangzb01 shelltest]# echo ${a[@]/b/100}  //將值b替換爲100並打印到桌面,此時並無保存數組替換後的值
1 2 a 100 c aaa
[root@wangzb01 shelltest]# echo ${a[@]}  //上一步並未賦值,所以數組沒有變化
1 2 a b c aaa

[root@wangzb01 shelltest]# a=(${a[@]/b/100})  //替換從新賦值給a[@]
[root@wangzb01 shelltest]# echo ${a[@]}  //打印從新賦值後的數組
1 2 a 100 c aaa
相關文章
相關標籤/搜索