2018-07-27筆記( shell學習)

20.1 shell腳本介紹

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

shell是什麼
shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操作系統,並處理各種各樣的操作系統的輸出結果,輸出到屏幕返回給用戶。這種對話方式可以是交互的方式(從鍵盤輸入命令,可以立即得到shell的迴應),或非交互(執行腳本程序)的方式
什麼是shell腳本?
當linux命令或語句不在命令下執行(嚴格說,命令行執行的語句也是shell腳本),而是通過一個程序文件執行時,該程序就被稱爲shell腳本或shell程序,shell程序很類似DOS系統下的批處理程序(擴展名*.bat)。用戶可以在shell腳本中敲入一系列的命令或命令語句組合。這些命令、變量和流程控制語句等有機的結合起來就形成了一個功能很強大的shell腳本。
shell腳本語言的種類
在UNIX/LINUX中主要有兩大類shell。

•Bourne shell包括sh、ksh和bash。
•Bourne shell (sh)
•Korn shell (ksh)
•Bourne Again shell (bash)
•POSIX shll (sh)
•C shell包括csh和tcsh。
•C shell (csh)
•TEXES/TOPS C shell(tcsh)

shell腳本語言是若類型語言,較爲通用的shell有標準的Bourne shell(sh)和C shell(csh)。其中Bource shell(sh)已經被bash shell取代。
查看系統的shell。

[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash #功能更強大
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh

20.2 shell腳本結構和執行

•開頭需要加#!/bin/bash,指定是哪個解釋器
•以#開頭的作爲解釋說明
•腳本的名字以.sh結尾,用於區分這是一個shell腳本
•執行方法有幾種
shell腳本的建立
在linux系統中,shell腳本(bash shll程序)通常是在編輯器(如vi/vim)中編寫,由Unix/Linux命令、bash shell命令、程序結構控制語句和註釋等內容組成
腳本開頭(第一行)
一個規範的shell腳本在腳本第一行會指出由哪個程序(解釋器)來執行腳本中的內容,這一行內容在linux bash編程中一般爲:
#! /bin/bash

#! /bin/sh <==255個字符以內
其中開頭的"#!"字符又稱爲幻數,在執行bash腳本的時候,內核會根據"#!"後的解釋器來確定該用哪個程序解釋這個腳本的內容。注意,這一行必須在每個腳本頂端的第一行,如果不是第一行則爲腳本註釋行
腳本註釋
在shell腳本中,跟在(#)井號後面的內容表示註釋,用來對腳本進行註釋說明,註釋部分不會被當做程序執行,僅僅是給用戶看,系統解釋器是看不到的,更不會執行。註釋可自成一行,也可以跟在腳本命令後面與命令在同一行
shell腳本的執行
當shell腳本運行時,它會先查找系統環境變量ENV,該變量指定了環境文件(通常是.bashrc、.bash_profile、/etc/bashrc、/etc/profile等),然後從該環境變量文件開始執行腳本,當讀取了ENV的文件後,shell會開始執行shell腳本中的內容。
特殊技巧:設置crond任務時,最好把系統環境變量在定時任務腳本中重新定義,否則,一些系統環境變量將不會被加載
執行說明
第一種方法是當腳本文件本身沒有可執行權限(即文件x位爲-號)時常使用的方法,或者文件開頭沒有指定解釋器。
例如:

[root@localhost ~]# cat test.sh 
echo 'i am shell'
[root@localhost ~]# sh test.sh 
i am shell
[root@localhost ~]# bash test.sh 
i am shell

第二種方法需要先將腳本文件的權限改爲可執行(即文件加X位),具體方法:chmod u+x script-name或chmod 755 script-name。然後通過腳本路徑就可以直接執行腳本。
例如:

[root@localhost ~]# ll test.sh 
-rw-rw-r--. 1 root root 1217 7月  27 13:57  test.sh
[root@localhost ~]# ./test.sh #使用第二種方式,"./"在當前目錄下執行test.sh腳本文件,無法使用tab自動補全
-bash: ./test.sh: Permission denied 
給test.sh添加可執行權限。
[root@localhost ~]# chmod u+x test.sh 
[root@localhost ~]# ./test.sh 
i am shell

第三种放法通常是使用source或"."點號讀入或加載指定的shell腳本文件(如test.sh),然後,依次執行指定shell腳本文件test.sh中的所有語句
例如:

[root@lamp ~]# . test.sh 
i am shell
[root@lamp ~]# source test.sh 
i am shell

說明:如果希望父shell調用子shell的變量、函數等,用source或"."點號執行腳本

20.3 date命令用法

命令:date
date 可以用來顯示或設定系統的日期與時間。
命令參數

-d<字符串>:顯示字符串所指的日期與時間。字符串前後必須加上雙引號; 
-s<字符串>:根據字符串來設置日期與時間。字符串前後必須加上雙引號;只有root權限才能設置,其他只能查看 
-u:顯示GMT; 
--help:在線幫助; 
--version:顯示版本信息

日期格式字符串列表

%H 小時(以00-23來表示)。 
%I 小時(以01-12來表示)。 
%K 小時(以0-23來表示)。 
%l 小時(以0-12來表示)。 
%M 分鐘(以00-59來表示)。 
%P AM或PM。 
%r 時間(含時分秒,小時以12小時AM/PM來表示)。 
%s 總秒數。起算時間爲1970-01-01 00:00:00 UTC。 
%S 秒(以本地的慣用法來表示)。 
%T 時間(含時分秒,小時以24小時制來表示)。 
%X 時間(以本地的慣用法來表示)。 
%Z 市區。 
%a 星期的縮寫。 
%A 星期的完整名稱。 
%b 月份英文名的縮寫。 
%B 月份的完整英文名稱。 
%c 日期與時間。只輸入date指令也會顯示同樣的結果。 
%d 日期(以01-31來表示)。 
%D 日期(含年月日)。 
%j 該年中的第幾天。 
%m 月份(以01-12來表示)。 
%U 該年中的週數。 
%w 該周的天數,0代表週日,1代表週一,異詞類推。 
%x 日期(以本地的慣用法來表示)。 
%y 年份(以00-99來表示)。 
%Y 年份(以四位數來表示)。 
%n 在顯示時,插入新的一行。 
%t 在顯示時,插入tab。 
MM 月份(必要) 
DD 日期(必要) 
hh 小時(必要) 
mm 分鐘(必要)
ss 秒(選擇性)

實例:
•年月日

[root@localhost ~]# date +"%Y-%m-%d" 
2018-07-29
[root@localhost ~]# date +"%y-%m-%d" 
18-07-29

•輸出昨天、前天,明天等的日期:

[root@localhost ~]# date -d "+1 day " +"%Y-%m-%d"
2018-07-28
[root@localhost ~]# date -d "+2 day " +"%Y-%m-%d"
2018-07-27
[root@localhost ~]# date -d "-1 day " +"%Y-%m-%d"
2018-07-30

•加減操作:

date -d "+1 day" +%Y%m%d   #顯示前一天的日期 
date -d "-1 day" +%Y%m%d   #顯示後一天的日期 
date -d "-1 month" +%Y%m%d #顯示上一月的日期 
date -d "+1 month" +%Y%m%d #顯示下一月的日期 
date -d "-1 year" +%Y%m%d  #顯示前一年的日期 
date -d "+1 year" +%Y%m%d  #顯示下一年的日期

設定時間:

date -s          #設置當前時間,只有root權限才能設置,其他只能查看 
date -s 20120523 #設置成20120523,這樣會把具體時間設置成空00:00:00 
date -s 01:01:01 #設置具體時間,不會對日期做更改 
date -s "01:01:01 2012-05-23" #這樣可以設置全部時間 
date -s "01:01:01 20120523"   #這樣可以設置全部時間 
date -s "2012-05-23 01:01:01" #這樣可以設置全部時間 
date -s "20120523 01:01:01"   #這樣可以設置全部時間

•顯示日曆

[root@localhost ~]# cal
      七月 2018     
日 一 二 三 四 五 六
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

20.4 shell腳本中的變量

•當腳本中使用某個字符串,多次頻繁並且字符串長度很長時,就應該使用變量代替
•使用條件語句時,常使用變量 if [ $a -gt 1];then ...;fi
•引用某個命令的結果時,用變量替代 n=wc -l 1.txt
•寫和用戶交互的腳本時,變量也是必不可少的 read -p "lnput a number:" n; echo $n 如果沒有寫這個n, 可以直接使用$REPLY
•內置變量 $0,$1,$2... $0表示腳本本身,$1 第一個參數,$2第二個... $#: 表示參數個數
•數學運算a=1;b=2;c=$($a+$b)或者$[$a+$b]

20.5 shell腳本中的邏輯判斷

Shell腳本中,充滿着各種邏輯判斷,是腳本中必備的
•if邏輯判斷格式

格式1:if 條件 ; then 語句; fi
格式2:if 條件; then 語句; else 語句; fi
格式3:if …; then … ;elif …; then …; else …; fi

•數學邏輯判斷表達式:

-gt (>);    大於    great than
-lt(<);      小於     less than
-ge(>=);  大於或等於   
-le(<=);   小於或等於
-eq(==);  等於     equal
-ne(!=)    不等於  not equa
- - - - - - - - - - - - - - - - - - - - - -
方括號裏面不能使用數學運算符<,>,=,等,兩邊中間都要有空格
要使用這些符號,只能使用兩個括號(()),不用空格
例如
if [ $a -gt $b ]等同if (($a>$b))
if [ $a -lt 5 ]等同if (($a<5))
if [ $b -eq 10 ]等if (($b==10))

•多個條件組合-a,-o

-a表示並且,全部條件都成立
-o或者或者,滿足一個條件成立
[root@localhost ~]# a=5;if [ $a -gt 4 -a $a -lt 6 ];then echo ok;fi
ok
[root@localhost ~]# a=5;if [ $a -gt 5 -o $a -lt 6 ];then echo ok;fi
ok

•可以使用 && || 結合多個條件

條件A&&條件B:A並且B
條件A||條件B:A或者B
if [ $a -gt 5 ] && [ $a -lt 10 ]; then
if [ $b -gt 5 ] || [ $b -lt 3 ]; then

•if邏輯判斷例子
格式1:if 條件 ; then 語句; fi

#!/bin/bash
a=5
if [ $a -gt 3 ]
then
       echo "ok"
fi

格式2:if 條件; then 語句; else 語句; fi

#!/bin/bash
a=5
if [ $a -gt 3 ]
then
    echo "ok"
else
    echo "nook"
fi

格式3:if …; then … ;elif …; then …; else …; fi

#!/bin/bash
a=5
if [ $a -lt 4 ]
then
    echo "<4"
elif [ $a -lt 6 ]
#注意elif可以嵌套多次的
then
    echo "<6 && >4"
else
    echo "nook"
fi

20.6 文件目錄屬性判斷

在shell中通常要和文件或者目錄打交道,那麼對於他們的屬性判斷十分重要

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

例子:

#!/bin/bash
file="/tmp/1.txt"
if [ -e $file ]
then 
       echo $file exist
else
      touch $file

&& ||特殊用法,省略if

1.txt不存在,&&表示前一條命令執行成功,纔會執行後面的命令
[root@localhost ~]# [ -e 1.txt ]&&touch 1.txt
[root@localhost ~]# ll
總用量 4
-rw-------. 1 root root 1418 4月  26 05:41 anaconda-ks.cfg
drwxr-xr-x  2 root root   60 6月  18 11:40 src1
1.txt不存在,||表示前一條命令執行不成功,纔會執行後面的命令
[root@localhost ~]# [ -e 1.txt ]||touch 1.txt
[root@localhost ~]# ll
總用量 4
-rw-r--r--  1 root root    0 7月  29 22:13 1.txt
-rw-------. 1 root root 1418 4月  26 05:41 anaconda-ks.cfg
drwxr-xr-x  2 root root   60 6月  18 11:40 src1

20.7 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… 
[ ] 中不能使用<,>,==,!=,>=,<=這樣的符號

例子:
if [ -z “$a” ] 這個表示當變量a的值爲空時會怎麼樣

#!/bin/bash
n='wc -l /tmp/1.txt'
if [ $n -lt 100 ]
then
       echo "line num less than 100"
fi
# 如果/tmp/1.txt文件爲空,或者被刪除的話,腳本就會運行出錯,出現bug
應該加上一個判斷條件
#!/bin/bash
n='wc -l /tmp/1.txt'
if [  -z "$n" ]
# [  -z "$n" ] 等同[ ! -n "$n" ],!表示取反
then
       echo "error"
       exit
elif [ $n -lt 100 ]
then
        echo "line num less than 100"
fi

或者
#!/bin/bash
if [ ! -f /tmp/1.txt ]
then
       echo "/tmp/1.txt is not exist"
       exit
fi

n='wc -l /tmp/1.txt'
if [ $n -lt 100 ]
then
        echo "line num less than 100"
fi

if [ -n “$a” ] 表示當變量a的值不爲空,也可以判斷文件,判斷文件時可以不加雙引號

if [ -n 01.sh ]; then echo "ok"; fi
另外
#!/bin/bash
if [ -n "$b" ]
then  
       echo $b
else
        echo "b is null"
fi

一條命令也可以作爲判斷條件。判斷user1用戶是否存在

if grep -wq 'user1'  /etc/passwd; then echo "user1 is exist"; else useradd user1;fi 
#grep -w 精準匹配單詞,加-q可以不顯示過濾信息

20.8/20.9 case判斷

case判斷格式

case 變量名 in
    value1)
      commond1
      ;;
    value2)
      commod2
      ;;
    value3)
      commod3
      ;;
esac

在case中,可以在條件中使用“|”,表示或的意思,如:

2|3)
    commond
    ;;

例子: 輸入一個同學的分數,判斷成績是否及格,優秀

[root@localhost sbin]# vim case1.sh
#!/bin/bash
read -p "Please input a number: " n
# read -p 是讀取用戶的輸入數據,定義到變量裏面
if [ -z "$n" ]
then
    echo "error not input"
    exit 1
#“exit 1”表示非正常運行導致退出程序
#退出之後,echo $?會返回1值,表示程序退出是因爲出錯了
fi

n1=`echo $n|sed 's/[0-9]//g'`
#判斷用戶輸入的字符是否爲純數字
#如果是數字,則將其替換爲空,賦值給$n1
if [ -n "$n1" ]
then
echo "Please input a number."
exit 1
#判斷$n1不爲空時(即$n不是純數字)再次提示用戶輸入數字並退出
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
#tag的作用是爲判斷條件設定標籤,方便後面引用
case $tag in
    1)
        echo "不及格"
        ;;
    2)
        echo "及格"
        ;;
    3)
        echo "良好"
        ;;
    4)
        echo "優秀"
        ;;
    *)
        echo "The number range is 0-100."
        ;;
esac

運行結果

[root@localhost shell]# sh case1.sh
Please input a number: 
error not input
[root@localhost shell]# sh case1.sh
Please input a number: 12a23
Please input a number.
[root@localhost shell]# sh case1.sh
Please input a number: 45
不及格
[root@localhost shell]# sh case1.sh
Please input a number: 65
及格
[root@localhost shell]# sh case1.sh
Please input a number: 85
良好
[root@localhost shell]# sh case1.sh
Please input a number: 95
優秀
[root@localhost shell]# sh case1.sh
Please input a number: 120
The number range is 0-100.

20.10 for循環

•格式:

for 變量名 in 條件; do ...; done

例子:
•用for循環計算1到100的總和

[root@localhost shell]# cat for.sh
#!/bin/bash
sum=0
for i in `seq 1 100`
do
    sum=$[$sum+$i]
done
echo $sum

#輸出的結果
[root@localhost shell]# sh for.sh 
5050

•文件列表循環

[root@localhost shell]# cat for2.sh 
#!/bin/bash
cd /etc/
for a in `ls /etc/`
do
    if [ -d $a ]
    then
        ls -d $a
    fi
done
#for循環是以空格、回車符作爲分割符分割。

20.11/20.12 while循環

•語法 while 條件; do ...; done
例子:
用while循環檢測系統1分鐘的負載,如果大於,發郵件通知

#!/bin/bash
while :
#while 跟冒號表示死循環
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" [email protected]
    fi
    sleep 30
done

循環判斷輸入的是否純數字

#!/bin/bash
while :
do
  read -p "Please input a number:" n
  if [ -z "$n" ]
  then
      echo "You did not enter the number."
      continue
  fi
  n1=`echo $n|sed 's/[0-9]//g'`
  if [ ! -z "$n1" ]
  then
      echo "You can only enter a pure number."
      continue
  fi
  break
done
echo $n

20.13 break跳出循環

break表示跳出循環,斷續執行後面的語句
例子

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

運行結果

[root@localhost ~]# sh break.sh
1
1
2
2
3
aaaaaa

可以看到上例中,只循環到第3次的時候,跳出了循環,直接執行了echo aaaaaa的語句

20.14 continue結束本次循環

continue結束本次循環,不執行後面的語句,直到循環結束

[root@localhost etc]# cat continue.sh 
#!/bin/bash
for i in `seq 1 5`
do
  echo $i
  if [ $i -eq 3 ]
  then
      continue
  fi
  echo $i
done
echo aaaaaa

運行結果

[root@localhost etc]# sh continue.sh 
1
1
2
2
3
4
4
5
5
aaaaaa

可以看到循環到第3次的時候,沒有執行後面的語句,直到循環結束

20.15 exit退出整個腳本

exit退出腳本

[root@localhost etc]# cat exit.sh 
#!/bin/bash
for i in `seq 1 5`
do
  echo $i
  if [ $i -eq 3 ]
  then
      exit
  fi
  echo $i
done
echo aaaaaa

運行結果

[root@localhost etc]# sh exit.sh 
1
1
2
2
3

可以看到第三次,直接退出了腳本

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章