2018-07-27筆記( shell學習)
?shell是一種腳本語言
?可以使用邏輯判斷、循環等語法
?可以自定義函數
?shell是系統命令的集合
?shell腳本可以實現自動化運維,能大大增加我們的運維效率
shell是什麽
shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操作系統,並處理各種各樣的操作系統的輸出結果,輸出到屏幕返回給用戶。這種對話方式可以是交互的方式(從鍵盤輸入命令,可以立即得到shell的回應),或非交互(執行腳本程序)的方式
什麽是shell腳本?
當linux命令或語句不在命令下執行(嚴格說,命令行執行的語句也是shell腳本),而是通過一個程序文件執行時,該程序就被稱為shell腳本或shell程序,shell程序很類似DOS系統下的批處理程序(擴展名*.bat)。用戶可以在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取代。
[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
可以看到第三次,直接退出了腳本
2018-07-27筆記( shell學習)