Shell綜述
簡單的說:shell是用戶和Linux操作系統之間接口,提供了與操作系統之間通訊的方式。
shell基本上是一個命令解釋器,它接收用戶命令(如ls等),然後調用相應的應用程序。
主要學習/bin/bash它兼容於sh,一句使用者需求,而加強的sh版本。
shell中的變量:變量的概念源於數學,在計算機中能存儲計算結果,活表示值。例如:y=5x+8其中y就是變量。環境變量對bash的影響:
PATH:能不能執行某命令和PATH有關,如果在PATH中找不到相關命令,屏幕會出現command not found
普通用戶PATH例子:
PATH=/sbin:/usr/java/jdk1.8.0_45-cloudera/bin:/usr/local/apache-ant/apache-ant-1.9.2/bin:/usr/local/apache-maven等
舉例:讀取登陸用戶名:echo $LOGINAME,讀取用戶home目錄:echo $HOME,讀取當前系統默認shell:echo $SHELL
讀取變量另一種格式:echo ${LOGNAME}
環境變量:使用env觀察環境變量--- env|more
Linux是一個多用戶多任務的操作系統,所以在Linux中不同用戶具有不同的運行環境,在這樣的不同環節中,可以爲不同的用戶指定不同的環境變量
舉例:使用set或env觀察環境變量
普通變量->環境變量:1、export 變量名=值,2、變量名1=值1,變量名2=值2,export 變量名1 變量名2
export var=teduhadoop -> env|grep var MAIL=/var/spool/mail/root var=teduhadoop
1)變量和值之間以一個等號"="連接(name=value)
2)變量、值和等號之間不能有空格
3)變量名稱只能是英文字母、數字、下劃線、但開頭不能是數字。
4)變量內容若有空格符可使用雙引號或者單引號將變量內容結合起來。(''單引號使特殊字符不生效,""雙引號生效)
5)變量內容由其他命令提供,使用$(其它命令)
例:version=$(uname):把變量version設定值爲命令uname
echo $version:和執行uname效果一樣,把系統版本打印出爲Linux
version=$(uname -a),echo $version 之後,則顯示出Linux系統的全部內容
version=$(uname),version=$version-$(uname-p),echo $version
6)通常變量名大寫爲系統默認變量,自己定義變量可以使用小寫,方便區分。
7)取消變量的定義:unset 變量名(如果取消系統環境變量的話,修改/etc/profile文件,否則重啓後該變量還中存在)
命令定義爲變量使用案例:
fname=$(uname-n)_$(date+%F)->echo $fname-> localhost.localdomain_2016-11-03
tar -zcf etc_${fname}.tar.gz /etc
8)變量總結:①全局變量:一般全大寫,如環境變量②:局部變量:腳本函數中的局部變量通常使用local
③把一個命令定義成一個變量④${WEEK}day若變量和其他字符組成新的變量就必須給變量加上大括號,否則容易出錯
9)數據重定向:
數據重定向就是將某個命令執行後應該要出現在屏幕上的數據,給他傳輸到其他的地方,例如傳輸到文件或是其它命令。通常執行一條命令的時候會有標準輸出和標準錯誤輸出,標準輸出是指命令執行之後,傳回正確信息的輸出目標,標準錯誤輸出是命令執行失敗後,所傳回錯誤信息的輸出目標。
數據重定向編號:
標準輸入(stdin):編號爲0
標準輸出(stdout):編號爲1
標準錯誤輸出(stderr):編號爲2
1>:以覆蓋的方法,將正確的數據輸出到文件;
1>>:以累加的方法,將正確的數據輸出到文件;
2>:以覆蓋的方法,將錯誤輸出的數據輸出到文件;
2>>:以累加的方法,將錯誤輸出的數據輸出到文件;
舉例:將ls的輸出重定向到ls.log當中
# ll 1>ls.log->cat ls.log
10)命令執行判斷:
$?:命令回傳值,&&:若cmd1執行完畢且正確執行($?=0),則開始執行cmd2,若cmd1執行完畢且錯誤
($?≠0),則cmd2不執行。
||:若cmd1執行完畢且正確執行($?=0),則cmd2不執行。若cmd1執行完畢且未錯誤($?≠0),則開始執行cmd2
舉例:如果/tmp/test存在,則創建/tmp/test/jinxf
ls /tmp/test && touch /tmp/test/jinxf:如果查詢/tmp/test存在,則執行touch這個創建文件的命令
11)管道命令:
利用Linux所提供的管道符"|"將兩個命令隔開,管道符左邊命令的輸出就會作爲管道符右邊命令的輸入。
連續使用管道意味着第一個命令的輸出會作爲,第二個夢裏的輸入,第二個命令的輸出又會作爲第三個命令
的輸入,以此類推。
舉例:將ls的查詢信息傳遞給grep命令進行搜索含"Music"。ls -a|grep Music
12)find命令(查找,搜索)
Linux最有用的命令之一,在一個目錄(及子目錄)中搜索文件,可以指定一些匹配條件,如:按文件名,
文件類型,用戶甚至是時間戳查找文件。
命令格式:find [path..] [-option]
path:find命令所查找的目錄路徑,例如用.來表示當前目錄,用/來表示系統跟目錄。
options:find命令常用選項:
print:將匹配的文件輸出到標準輸出。
size:匹配文件大小。find./ -size 0; 顯示文件大小爲0的文件
name:按照文件名查找文件。find / -name demo 在/目錄及子目錄下面查找名字爲demo的文件。
find . -name "*.java" 在當前目錄及其子目錄(用"."表示中查找任何擴展名爲"java"的文件)
perm按照權限來查找文件:find . -perm 755 [-print] 在當前目錄下查找文件權限爲755的文件,
即文件所有者讀,寫,執行,組與其他用戶可以讀,執行的文件。
user按照文件所有者來查找文件,find ~ -user root [-print]在$HOME目錄中查找文件屬性爲root
的文件。
group按照文件所屬的組來查找文件。
find / -group root [-print]在目錄下查找屬於root的用戶組文件。
mtime -n +n :按照文件的更改時間來查找文件,-n表示文件更改時間距現在n天內,+n表示文件更改時間
距現在n天前。
find / -mtime -5 print 在系統跟目錄下查找更改時間在5日以內的文件。
find / -mtime +3 -print 在/目錄下查找更改時間在3日以前的文件。
nogroup:查找無有效所屬組的文件,即該文件所屬組/etc/groups中不存在。
find / -nogroup -print
type作爲find命令常用選項存在,type查找某一類型文件:
b--塊設備文件。d--目錄。c--字符設備文件。p--管道文件。l--符號連接文件。f--普通文件
find /etc -type d -print 在/etc目錄下查找所有的目錄。
find . ! -type d -print 在當前目錄下查找除目錄意外的所有類型文件。
find /etc -type l -print 在/etc目錄下查找所有的符號鏈接文件。
size n:[c]查找文件長度爲n的文件,帶有c時表示文件長度以字節計。
find . -size +1000c -print在當前目錄下查找文件長度大於1000字節的文件。
sed命令:非交互式文本處理工具,默認情況下,所有的輸出行都打印到屏幕上,sed編程器逐行處理
文件(或輸入),並將結果結果發送到屏幕。具體過程如下:
sed把當前正在處理的行保存在一個臨時緩存區中,(也成文模式空間)然後處理臨時緩衝區的行,完成後
把該行發到屏幕上,sed每處理完一行就將其從臨時緩衝區刪除,然後將下一行讀入再處理顯示。處理完
文件最後一行,sed便結束運行。sed把每一行都存在臨時緩衝區中,對這個副本進行編輯,所以不會修改
源文件。sed命令格式:sed [option] "[action]" [filename]
option:h或-help 顯示幫助。n僅顯示script處理後的結果,V或-version顯示版本信息。
e:允許輸入數據應用多條sed命令進行編輯。f直接將sed的動作寫在一個文件內。-f filename則可以運行
filename內的sed動作。
13)grep命令:grep(global search regular expression(RE) and print out the line,全面搜索正則表達式並把行打印出來)
一種強大的文件搜索工具,它能使用正則表達式搜索文本,並把匹配的行打印出來。
grep命令的一般形式,grep [OPTIONS] PATTERN [FILE...],-?:同時顯示匹配行上行下的?行。
如:grep -2 pattern filename同時顯示匹配行的上下2行。
14)tail:(跟蹤,監視)把某個檔案文件的最後幾行顯示到終端上,如果該檔案有更新,tail會自動刷新,確保你看到最新的
檔案內容。tail [-F] [-c Number | -n Number | -m Number | -b Number | -k Number] [File]
-F該參數用戶見識File文件增長。-c Number 從Number字節位置讀取指定文件。
-n Number從Number行位置讀取指定文件。-m Number從Number多字節字符位置讀取指定文件,比如你的文件
如果包含中文字,如果指定-c參數,可能導致截斷,但是使用-m會避免該問題。
例子:tail -F filename 顯示filename文件的尾部內容(默認10行,相當於添加參數,-n 10 )
刷新顯示在屏幕上,退出ctrl+c
tail -n 20 filename 顯示filename最後20行
15)sort:sort命令默認的情況下是按照字符排序。-n:按照數值排序,-u不出現重複的行。-t指定分段的符號
-k之地你給的第幾個段,-r逆向排序
例子:原始文件demo,cat demo :192.168.1.1 192.168.1.3 192.168.1.5 192.168.1.4
對文件進行排序: sort demo ---> 192.168.1.1 192.168.1.3 192.168.1.4 192.168.1.5
對文件逆序排序:sort -r demo > d1 ->192.168.1.5 192.168.1.4 192.168.1.3 192.168.1.1
對文件進行制定分隔符,並對第四個字段排序:sort -t "." -k 4 demo(以.爲分割,第四段就是例子中的最後一段數字)
16)cut:在文件中負責剪切數據,命令格式:cut [-option] filename
option:-b字節,-c字符,-f提取第幾列,-d按指定分隔符分割列。
例:每一行第五到第七字節:cut -b 5-7 st >demo
以點爲分隔符,獲取第二個字段:cut -d . -f 2 demo
17)history命令:顯示全部歷史,history 5 顯示執行過的上5條命令,history !!運行上一條命令history !88運行第88條命令
Shell腳本編寫
shell script其實就是純文本文件,以固定的語法組織起來,可以編輯這個文件,讓這個文件幫助我們一次執行多個命令。可以通過一些運算與邏輯判斷來幫我們達成某些複雜的功能。shell命令執行是從上而下,從左而右執行;命令,選項與參數間的多個空格會被忽略空白行也被忽略調,tab被視爲空格;如果讀取一個Enter符號(CR),就嘗試開始執行該行命令
#後面內容爲註釋。
shell的執行:
程序文件名是:/home/shell.sh,執行腳本有三種方式:
①直接執行(shell.sh文件必須具備可讀與可執行(rx)的權限):
絕對路徑:運行/home/shell.sh來執行指令,相對路徑:cd到/home/,使用./shell.sh執行。
②source 執行: source shell.sh
③bash執行:bash shell.sh sh shell.sh
shell腳本案例:第一行#!/bin/bash,告訴系統如何執行腳本。當採用直接執行(不是用類似sh xxx.sh)時
#!/bin/bash 此行必須有,且要放在首行。
#Shows system date 除了第一行的之外#都是註釋,其他爲程序部分。
echo $(date + %F) exit 0,以0作爲該腳本的執行返回值。執行正常退出返回0,一個腳本執行完成
exit 0 之後的shell進程可以通過$?獲取執行結果:echo $?
shell腳本--數值運算:簡單的加減乘除,格式:$((運算內容)),兩個括號爲規定
例:兩數相稱(交互shell腳本)
#!/bin/bash
# User inputs 2 integer numbers;program will cross these two
read -p "first number: "num1 ----把信息提示出來
read -p "second number: "num2 ----把信息提示出來
total=$(($num1*num2))
echo -e "\nThe result of $num1 * $sum2 is ==> $total" exit 0
test判斷命令:使用範圍:test -e demo.txt
-e該文件是否存在,-f該文件是否存在且爲文件,-d該文件名是否存在且爲目錄
-b該文件是否存在且爲一個block device 裝置,-c該文件是否存在企鵝爲一個character device裝置
-S發u胃不好事故覅有詞語不再且爲一個Socket文件,-p該文件是否村子啊且爲一個FIFO(pipe)文件
-L該文件是否存在且爲連接文件。-nt 判斷file1是否比file2新,-ot判斷file1是否比file2舊
-ef 判斷兩個文件是否爲同一個文件。
判斷符號[](基本跟test相同):
[ ]腳本返利(注意[]和腳本之間保留空格)
==和!=用戶比較字符串;整數比較只能使用-eq,-gt這種形式
[]中的邏輯和邏輯或使用-a和-o表示。
&& ,|| <和>操作符如果出現按在[]結構中的話,會報錯。
#!/bin/bash
#this shell show user's choice
read -p "Please input(Y/N):"yn
["$yn" == "Y" -o "$yn" == "y"]&&echo "choice Yes"&&exit 0
["$yn" == "N" -o "$yn" == "n"]&&echo "choice No"&&exit 0
Shell script默認參數:
比如,ls -al其中-al就是shell腳本參數,那麼我們自己寫的腳本參數該如何使用?
/path/to/scriptname arg1 arg2 arg3 arg4
$0 $1 $2 $4
$0:代表腳本程序本身,$1,$2代表後面第一個參數,第二個參數,等等
$# :代表後面參數個數,以上邊爲例,這裏顯示爲4
$@:代表"$1""$2""$3""$4",每個變量是肚子裏的(用雙引號括起來)
$*:代表"$1 $2 $3 $4"
Shell的條件判斷語句:
if [ 條件判斷 ] 前後要有空格
then 換行時候用then
if [ 條件判斷 ]; then
條件成立執行,命令;fi 將if反過來寫,就稱爲f結束if語句
&&代表 and || 代表or。
例子:
#!/bin/bash
#compare the size of the two numbers
a=12
b=13
if[$a -gt $b]
then
echo "yew $a>$b"
exit 0
fi
if[$a -le $b];then
echo "yew $a<=$b"
fi
多分支結構:還有一種是基於case的條件語句!!!
if [ 條件1 ];then ----條件1成立,執行指令集1
elif [ 條件2 ];then -----條件2成立,執行指令集2
else 條件都不成立,執行指令集3
fi
Shell的循環語句:
循環可以不斷的執行某個程序段落,直到用戶設置的條件達成位置,這被稱之爲不定循環,除這之外,還有另外一種已經固定要執行多少此循環這稱之爲固定循環。
不定循環:while do done,util do done
固定循環:for ... do done
1)while循環語句:
while [ condition條件 ] do
命令
done
例:每隔兩面打印系統的負載情況。 例:使用while循環,編寫shell腳本,計算1+2+3+...+100的和並輸出
vim while1.sh vim while2.sh
#!/bin/bash #!/bin/bash
while true sum=0
do i=1
uptime #系統負載情況 while [$i -le 100] #while和[之間要加一個空格,true則執行
sleep 2 #休眠2秒 do
done i=$(($i+1)) #運算結果爲變量賦值可以使用$((...))
ctrl+c 結束死循環。 sum=$(($sum+$i))
done
echo "the result of '1+2+3+...+100'" is $sum
2)until循環語句: --------------------->舉例:
until [ condition條件 ]; do #!/bin/bash
命令 i=0
done until [ "$i" -gt 5 ] #大於5
do
let square=i*i
echo "$i * $i = $square"
let "i++"
done
3)for 循環語句: --------------------->舉例:
for...do...done循環 for 男人 in 世界
語法:for 變量名 in 變量取值列表 do
do if [有房]&&[有車]&&[存款]&&[會做家務]&&[帥氣]; then
命令 echo "我喜歡"
done else
提示:在此結構中"in 變量取值列表" 可省略,省略時 rm -f男人;
相當於使用for i in "$@" fi;
done
例子2:直接列出變量表所有元素,打印5,4,3,2,1
方法1:直接列出元素方法
#!/bin/bash
for num in 5 4 3 2 1 #=>需要空格隔開
do
echo $num
done
[]和[[]]區別請參照:
http://www.zsythink.net/archives/2252
在bash中,$( )與``(反引號)都是用來作命令替換的。
shell中各種括號()、(())、[]、[[]]、{}的作用:
單括號():
另開命令組——小括號中的內容會開啓一個子shell獨立運行;括號中以分號連接,最後一個命令不需要;各命令和括號無空格
得到命令輸出——a=$(command), 等同於a=$`command`,得到命令輸出傳遞給變量a
初始化數組——array=(a b c d)
雙括號(()):
省去$符號的算術運算—— for((i=0;i<5;i++)); if (($i<5)); a=5; ((a++)) 可將 $a 重定義爲6;括號內支持多個表達式用逗號分開。
C語言規則運算——$((exp)),exp爲符合C語言規則的運算符,表達式
跨進制運算——二進制、八進制、十六進制運算時,輸出結果全都自動轉化成了十進制。如:echo $((16#5f)) 結果爲95 (16進位轉十進制)
單中括號[ ]:
字符串比較——==和!=
整數比較——不等於:-gt:大於;-lt :小於;-eq:等於;-ne
數組索引——array[0]
雙中括號[[]]:
字符串比較——可以把右邊的作爲一個模式,而不僅僅是一個字符串,比如[[ hello == hell? ]],結果爲真。[[ ]] 中匹配字符串或通配符,不需要引號。
邏輯運算符——防止腳本許多邏輯錯誤,比如,&&、||、<和> 操作符能夠正常存在於[[ ]]條件判斷結構中,但是如果出現在[ ]結構中的話,會報錯。
比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不適用雙括號, 則爲if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
退出碼——bash把雙中括號中的表達式看作一個單獨的元素,並返回一個退出狀態碼。
if ($i<5)
if [ $i -lt 5 ]
if [ $a -ne 1 -a $a != 2 ]
if [ $a -ne 1] && [ $a != 2 ]
if [[ $a != 1 && $a != 2 ]]
for i in $(seq 0 4);do echo $i;done
for i in `seq 0 4`;do echo $i;done
for ((i=0;i<5;i++));do echo $i;done
for i in {0..4};do echo $i;done
大括號{}:
創建匿名函數——不會新開進程,括號內變量餘下仍可使用。括號內的命令間用分號隔開,最後一個也必須有分號。{}的第一個命令和左括號之間必須要有一個空格。特殊替換——${var:-string},${var:+string},${var:=string},${var:?string}
特殊替換——${var:-string},${var:+string},${var:=string},${var:?string}
①${var:-string}和${var:=string}:若變量var爲空,則用在命令行中用string來替換${var:-string},否則變量var不爲空時,則用變量var的值來替換${var:-string};不同之處是${var:=string}常用於判斷var是否賦值,沒有的話則給var賦上一個默認值。
② ${var:+string}:替換規則和上面的相反,即只有當var不是空的時候才替換成string,若var爲空時則不替換或者說是替換成變量 var的值,即空值。(因爲變量var此時爲空,所以這兩種說法是等價的)
③${var:?string}:替換規則爲:若變量var不爲空,則用變量var的值來替換${var:?string};若變量var爲空,則把string輸出到標準錯誤中,並從腳本中退出。我們可利用此特性來檢查是否設置了變量的值。
注意:在上面這五種替換結構中string不一定是常值的,可用另外一個變量的值或是一種命令的輸出。
模式匹配替換——${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
# 是去掉左邊(在鍵盤上#在$之左邊);% 是去掉右邊(在鍵盤上%在$之右邊);#和%中的單一符號是最小匹配,兩個相同符號是最大匹配。
第一種模式:${variable%pattern}。shell在variable中查找,看它是否一給的模式pattern結尾,如果是,把variable去掉右邊最短的匹配模式
第二種模式: ${variable%%pattern},這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,把variable中去掉右邊最長的匹配模式
第三種模式:${variable#pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern開始,如果是,把variable中去掉左邊最短的匹配模式
第四種模式: ${variable##pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,把variable中去掉左邊最長的匹配模式
這四種模式中都不會改變variable的值,其中,只有在pattern中使用了*匹配符號時,%和%%,#和##纔有區別。結構中的pattern支持通配符,*表示零個或多個任意字符,?表示僅與一個任意字符匹配,[...]表示匹配中括號裏面的字符,[!...]表示不匹配中括號裏面的字符。
技巧小結
字符串比較用雙中括號[[ ]];算數比較用單中括號[ ]——左右留空格
算數運算用雙小括號(( )) ;shell命令及輸出用小括號( )——左右不留空格
快速替換用花括號{ }——左右留空格
反單引號起着命令替換的作用` `