shell基礎知識
什么是Shell
Shell是命令解釋器(command interpreter),是Unix操作系統的用戶接口,程序從用戶接口得到輸入信息,shell將用戶程序及其輸入翻譯成操作系統內核(kernel)能夠識別的指令,並且操作系統內核執行完將返回的輸出通過shell再呈現給用戶,下圖所示用戶、shell和操作系統的關系:
Shell也是一門編程語言,即shell腳本,shell是解釋執行的腳本語言,可直接調用linux命令。 .java -> .class
一個系統可以存在多個shell,可以通過cat /etc/shells命令查看系統中安裝的shell,不同的shell可能支持的命令語法是不相同的
Shell種類
操作系統內核(kernel)與shell是獨立的套件,而且都可被替換:
不同的操作系統使用不同的shell;
同一個kernel之上可以使用不同的shell。
常見的shell分為兩大主流:
sh:Linux常用的
Bourne shell(sh) ,Solaris,hpux默認shell
Bourne again shell(bash) ,Linux系統默認shell
csh: Unix常用的
C shell(csh)
tc shell(tcsh)
查看使用Shell
Shell環境定義
臨時環境變量
所謂臨時變量是指在用戶在當前登陸環境生效的變量,用戶登陸系統后,直接在命令行上定義的環境變量便只能在當前的登陸環境中使用。當退出系統后,環境變量將不能下次登陸時繼續使用。
將環境變量永久生效
通過將環境變量定義寫入到配置文件中,用戶每次登陸時系統自動定義,則無需再到命令行重新定義。定義環境變量的常見配置文件如下:
/etc/profile 針對系統所有用戶生效,此文件應用於所有用戶每次登陸系統時的環境變量定義 系統環境變量
$HOME_name/.bash_profile 針對特定用戶生效,$HOME為用戶的宿主目錄,當用戶登陸系統后,首先繼承/etc/profile文件中的定義,再應用$HOME/.bash_profile文件中的定義。 用戶環境變量
系統預定義的環境變量
系統環境變量對所有用戶有效,如:$PATH、$HOME、$SHELL、$PWD等等,如下用echo命令打印上述的系統環境變量:
shell腳本編程
同傳統的編程語言一樣,shell提供了很多特性,這些特性可以使你的shell腳本編程更為有用。
創建Shell腳本
一個shell腳本通常包含如下部分:
首行
第一行內容在腳本的首行左側,表示腳本將要調用的shell解釋器,內容如下:
#!/bin/bash
#!符號能夠被內核識別成是一個腳本的開始,這一行必須位於腳本的首行,/bin/bash是bash程序的絕對路徑,在這里表示后續的內容將通過bash程序解釋執行。
創建腳本三種方式
#echo “”> firsht.sh
#touch firsht.sh
#vim firsth.sh
注釋
注釋符號# 放在需注釋內容的前面,如下:
內容
可執行內容和shell結構
Shell腳本的權限
一般情況下,默認創建的腳本是沒有執行權限的
沒有權限不能執行,需要賦予可執行權限
Shell腳本的執行
1 輸入腳本的絕對路徑或相對路徑
/root/helloWorld.sh
./helloWorld.sh
2 bash或sh +腳本
bash /root/helloWorld.sh
sh helloWorld.sh
注:當腳本沒有x權限時,root和文件所有者通過該方式可以正常執行。
3 在腳本的路徑前再加". " 或source
source /root/helloWorld.sh
. ./helloWorld.sh
區別:第一種和第二種會新開一個bash,不同bash中的變量無法共享
另起一個shell #bash
但是使用第三種方式 腳本.sh 這種方式是在同一個shell里面執行的。
可以使用pstree查看
source eg.sh
Shell變量
變量:是shell傳遞數據的一種方式,用來代表每個取值的符號名。
當shell腳本需要保存一些信息時,如一個文件名或是一個數字,就把它存放在一個變量中。
變量設置規則:
1,變量名稱可以由字母,數字和下划線組成,但是不能以數字開頭,環境變量名建議大寫,便於區分。
2,在bash中,變量的默認類型都是字符串型,如果要進行數值運算,則必須指定變量類型為數值型。
3,變量用等號連接值,等號左右兩側不能有空格。
4,變量的值如果有空格,需要使用單引號或者雙引號包括。//注意要是英文輸入法那種
變量分類
Linux Shell中的變量分為用戶自定義變量,環境變量,位置參數變量和預定義變量。
可以通過set命令查看系統中存在的所有變量
系統變量:保存和系統操作環境相關的數據。$HOME、$PWD、$SHELL、$USER等等
位置參數變量:主要用來向腳本中傳遞參數或數據,變量名不能自定義,變量作用固定。
預定義變量:是Bash中已經定義好的變量,變量名不能自定義,變量作用也是固定的。
用戶自定義變量
用戶自定義的變量由字母或下划線開頭,由字母,數字或下划線序列組成,並且大小寫字母意義不同,變量名長度沒有限制。
設置變量:
習慣上用大寫字母來命名變量。變量名以字母表示的字符開頭,不能用數字。
變量調用
在使用變量時,要在變量名前加上前綴“$”.
使用echo 命令查看變量值。eg:echo $A
變量賦值:
1,定義時賦值:
變量=值
等號兩側不能有空格
eg:
STR="hello world"
A=9
2, 將一個命令的執行結果賦給變量
A=`ls -la` 反引號,運行里面的命令,並把結果返回給變量A
A=$(ls -la) 等價於反引號
eg: aa=$((4+5))
bb=`expr 4 + 5 `
3,將一個變量賦給另一個變量
eg : A=$STR
變量疊加
eg:#aa=123
eg:#cc="$aa"456
eg:#dd=${aa}789
單引號和雙引號的區別:
現象:單引號里的內容會 全部輸出,而雙引號里的內容會有變化
原因:單引號會將所有特殊字符脫意
NUM=10
SUM="$NUM hehe" echo $SUM 輸出10 hehe
SUM2='$NUM hehe' echo $SUM2 輸出$NUM hehe
列出所有的變量:
# set
刪除變量:
# unset NAME
eg :
# unset A 撤銷變量 A
# readonly B=2 聲明靜態的變量 B=2 ,不能 unset
用戶自定義的變量,作用域為當前的shell環境。
環境變量
用戶自定義變量只在當前的shell中生效,而環境變量會在當前shell和其所有子shell中生效。如果把環境變量寫入相應的配置文件,那么這個環境變量就會在所有的shell中生效。
export 變量名=變量值 申明變量
作用域:當前shell以及所有的子shell
位置參數變量
$n |
n為數字,$0代表命令本身,$1-$9代表第一到第9個參數, 十以上的參數需要用大括號包含,如${10}。 |
$* |
代表命令行中所有的參數,把所有的參數看成一個整體。以"$1 $2 … $n"的形式輸出所有參數 |
$@ |
代表命令行中的所有參數,把每個參數區分對待。以"$1" "$2" … "$n" 的形式輸出所有參數 |
$# |
代表命令行中所有參數的個數。添加到shell的參數個數 |
shift指令:參數左移,每執行一次,參數序列順次左移一個位置,$# 的值減1,用於分別處理每個參數,移出去的參數不再可用
$* 和 $@的區別
$* 和 $@ 都表示傳遞給函數或腳本的所有參數,不被雙引號" "包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數
當它們被雙引號" "包含時,"$*" 會將所有的參數作為一個整體,以"$1 $2 … $n"的形式輸出所有參數;"$@" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數
shell腳本中執行測試:
輸出結果:
預定義變量
$? |
執行上一個命令的返回值 執行成功,返回0,執行失敗,返回非0(具體數字由命令決定) |
$$ |
當前進程的進程號(PID),即當前腳本執行時生成的進程號 |
$! |
后台運行的最后一個進程的進程號(PID),最近一個被放入后台執行的進程 & |
# vi pre.sh
pwd >/dev/null
echo $$
ls /etc >/dev/null &
echo $!
Linux文件默認是沒有x權限的 而文件是有的
read命令
read [選項] 值
read -p(提示語句) -n(字符個數) -t(等待時間,單位為秒) –s(隱藏輸入) 對應密碼那些輸入
eg:
read –t 30 –p “please input your name: ” NAME
echo $NAME
read –s –p “please input your age : ” AGE
echo $AGE
read –n 1 –p “please input your sex [M/F]: ” GENDER
echo $GENDER
按住Ctrl +退格 才可以退
運算符
num1=11
num2=22
sum=$num1+$num2
echo $sum
格式 :expr m + n 或$((m+n)) 注意expr運算符間要有空格
expr命令:對整數型變量進行算術運算
(注意:運算符前后必須要有空格)
expr 3 + 5
expr 3 – 5
echo `expr 10 / 3`
10/3的結果為3,因為是取整
expr 3 \* 10
\ 是轉義符
計算(2 +3 )×4 的值
1 .分步計算
S=`expr 2 + 3`
expr $S \* 4
2.一步完成計算
expr `expr 2 + 3` \* 4
S=`expr \`expr 2 + 3\` \* 4`
echo $S
或
echo $(((2 + 3) * 4))
$()與${}的區別
$( )的用途和反引號``一樣,用來表示優先執行的命令
eg:echo $(ls a.txt)
${ } 就是取變量了 eg:echo ${PATH}
$((運算內容)) 適用於數值運算
eg: echo $((3+1*4))
條件測試
內置test命令
內置test命令常用操作符號[]表示,將表達式寫在[]中,如下:
[ expression ] 注意空格
或者:
test expression
注意:expression首尾都有個空格
eg: [ ] ;echo $?
測試范圍:整數、字符串、文件
表達式的結果為真,則test的返回值為0,否則為非0。
當表達式的結果為真時,則變量$?的值就為0,否則為非0
字符串測試:
test str1 == str2 測試字符串是否相等 =
test str1 != str2 測試字符串是否不相等
test str1 測試字符串是否不為空,不為空,true,false
test -n str1 測試字符串是否不為空 注意str1加雙引號和不加的區別
test -z str1 測試字符串是否為空
eg:
name=linzhiling
[ “$name” ] && echo ok
; 命令連接符號
&& 邏輯與 條件滿足,才執行后面的語句
[ -z “$name” ] && echo invalid || echo ok
|| 邏輯或,條件不滿足,才執行后面的語句
test “$name” == ”yangmi” && echo ok || echo invalid
整數測試:
test int1 -eq int2 測試整數是否相等 equals
test int1 -ge int2 測試int1是否>=int2
test int1 -gt int2 測試int1是否>int2
test int1 -le int2 測試int1是否<=int2
test int1 -lt int2 測試int1是否<int2
test int1 -ne int2 測試整數是否不相等
eg:
test 100 –gt 100
test 100 –ge 100
如下示例兩個變量值的大小比較:
-gt表示greater than大於的意思,-le表示less equal表示小於等於。
文件測試:
test -d file ;echo $? 指定文件是否目錄
test –e file ;echo $? 文件是否存在 exists
test -f file ;echo $? 指定文件是否常規文件
test –L File ;echo $? 文件存在並且是一個符號鏈接
test -r file 指定文件是否可讀
test -w file 指定文件是否可寫
test -x file 指定文件是否可執行
eg:
test -d install.log
test –r install.log
test –f xx.log ; echo $?
[ -L service.soft ] && echo “is a link”
test -L /bin/sh ;echo $?
[ -f /root ] && echo “yes” || echo “no”
多重條件測試:
條件1 –a 條件2 邏輯與 兩個都成立,則為真
條件1 –o 條件2 邏輯或 只要有一個為真,則為真
! 條件 邏輯非 取反
eg:
num=520
[ -n “$num” –a “$num” –ge 520 ] && echo “marry you” || echo “go on”
age=20
pathname=outlog
[ ! -d“$ pathname”] && echo usable || echo used
流程控制語句
if/else命令
1, 單分支if條件語句
if [ 條件判斷式 ]
then
程序
fi
或者
if [ 條件判斷式 ] ; then
程序
fi
eg:#!/bin/sh
if [ -x /etc/rc.d/init.d/httpd ]
then
/etc/rc.d/init.d/httpd restart
fi
單分支條件語句需要注意幾個點
if語句使用fi結尾,和一般語言使用大括號結尾不同。
[ 條件判斷式 ] 就是使用test命令判斷,所以中括號和條件判斷式之間必須有空格
then后面跟符號條件之后執行的程序,可以放在[]之后,用“;”分割,也可以換行寫入,就不需要";"了。
2,多分支if條件語句
if [ 條件判斷式1 ]
then
當條件判斷式1成立時,執行程序1
elif [ 條件判斷式2 ]
then
當條件判斷式2成立時,執行程序2
...省略更多條件
else
當所有條件都不成立時,最后執行此程序
fi
示例:
read -p "please input your name: " NAME
eg:
#!/bin/bash
read -p "please input your name:" NAME
#echo $NAME
if [ $NAME == root ]
then
echo "hello ${NAME}, welcome !"
elif [ $NAME == tom ]
then
echo "hello ${NAME}, welcome !"
else
echo "SB, get out here !"
fi
case命令
case命令是一個多分支的if/else命令,case變量的值用來匹配value1,value2,value3等等。匹配到后則執行跟在后面的命令直到遇到雙分號為止(;;)case命令以esac作為終止符。
格式
#!/bin/bash
case $1 in
start)
echo "starting"
;;
Stop)
echo "stoping"
;;
*)
echo "Usage: {start|stop}"
esac
for循環
for循環命令用來在一個列表條目中執行有限次數的命令。比如,你可能會在一個姓名列表或文件列表中循環執行同個命令。for命令后緊跟一個自定義變量、一個關鍵字in和一個字符串列表(可以是變量)。第一次執行for循環時,字符串列表中的第一個字符串會賦值給自定義變量,然后執行循環命令,直到遇到done語句;第二次執行for循環時,會右推字符串列表中的第二個字符串給自定義變量,依次類推,直到字符串列表遍歷完。
第一種:
for N in 1 2 3
do
echo $N
done
或
for N in 1 2 3; do echo $N; done
或
for N in {1..3}; do echo $N; done
第二種:
for ((i = 0; i <= 5; i++))
do
echo "welcome $i times"
done
或
for ((i = 0; i <= 5; i++)); do echo "welcome $i times"; done
練習:計算從1到100的加和。
while循環
while命令根據緊跟其后的命令(command)來判斷是否執行while循環,當command執行后的返回值(exit status)為0時,則執行while循環語句塊,直到遇到done語句,然后再返回到while命令,判斷command的返回值,當得打返回值為非0時,則終止while循環。
第一種
while expression
do
command
…
done
練習:求1-10 各個數的平方和
第二種方式:
自定義函數
函數代表着一個或一組命令的集合,表示一個功能模塊,常用於模塊化編程。
以下是關於函數的一些重要說明:
在shell中,函數必須先定義,再調用
使用return value來獲取函數的返回值
函數在當前shell中執行,可以使用腳本中的變量。
函數的格式如下:
函數名()
{
命令1…..
命令2….
return 返回值變量
}
[ function ] funname [()]
{
action;
[return int;]
}
function start() / function start / start()
eg:
注意:
如果函數名后沒有(),在函數名和{ 之間,必須要有空格以示區分。
函數返回值,只能通過$? 系統變量獲得,可以顯示加:return 返回值,如果不加,將以最后一條命令運行結果,作為返回值。 return后跟數值n(0-255)
腳本調試
sh -x script
這將執行該腳本並顯示所有變量的值。
在shell腳本里添加
set -x 對部分腳本調試
sh -n script
不執行腳本只是檢查語法的模式,將返回所有語法錯誤。
sh –v script
執行並顯示腳本內容
awk和sed
cut [選項] 文件名 默認分割符是制表符
選項:
-f 列號: 提取第幾列
-d 分隔符: 按照指定分隔符分割列
eg:#cut -f 2 aa.txt 提取第二列
eg:#cut -d ":" -f 1,3 /etc/passwd 以:分割,提取第1和第3列
eg:#cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1 獲取所有可登陸的普通用戶用戶名
cut的局限性 不能分割連續空格 df -h 不能使用cut分割
df -h | grep sda1 | cut -f 5
awk
一個強大的文本分析工具
把文件逐行的讀入,以空格為默認分隔符將每行切片空格可以是連續的空格,切開的部分再進行各種分析處理。
語法:awk ‘條件1{動作1}條件2{動作2}...’文件名
條件(Pattern):
一般使用關系表達式作為條件: > >= <=等
動作(Action):
格式化輸出
流程控制語句
eg:#df -h | awk '{print $1 "\t" $3}' 顯示第一列和第三列
print 有自動換行
printf 不能換行
FS內置變量 //默認第一行不會進行分割
eg:# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {print $1 "\t"$3 }' 輸出可登陸用戶的用戶名和UID,這里使用FS內置變量指定分隔符為:,而且使用BEGIN保證第一行也操作,因為awk命令會在讀取第一行后再執行條件
指定分隔符還可以用-F更簡單
eg:# cat /etc/passwd | grep "/bin/bash" | awk -F: '{print $1 "\t"$3 }' 效果同上
eg:判斷一下根目錄的使用情況
#df -h |grep sda1 | awk '{print $5}' | awk -F% '{print $1} $1<80{print "info"}$1>80{print "warning"}'
BEGIN 在所有數據讀取之前執行
eg:#awk 'BEGIN {printf "first Line \n"} {printf $2 }' aa.txt 在輸出之前使用BEGIN輸出內容
END 在所有數據執行之后執行
eg:#awk 'END {printf "The End \n"} {print $2}' aa.txt 所有命令執行完后,輸出一句"The End"
# df -h | grep sda2 | awk '{print $5}' | awk -F% '{print $1}'
# df -h | grep sda2 | awk '{print $5}' | cut -d"%" -f 1
獲取所有用戶信息里的用戶名:
cat /etc/passwd | awk -F: '{print $1}'
awk -F: '{print $1}' /etc/passwd
獲取當前機器的ip地址:
# ifconfig eth0 | grep 'inet addr' | awk -F: '{print $2}' | awk '{print $1}'
sed: stream editor
s e d是一個非交互性文本流編輯器。它編輯文件或標准輸入導出的文本拷貝。標准輸入可 能是來自鍵盤、文件重定向、字符串或變量,或者是一個管道的文本。
注意: s e d 並不與初始化文件打交道, 它操作的只是一個拷貝,然后所有的改動如果沒有重定向到一個文件,將輸出到屏幕。
語法:sed [選項]’[動作]’ 文件名
常用選項:
-n 使用安靜(silent)模式。顯示經過sed特殊處理的數據。
-e 允許多點編輯。
-i 直接修改讀取的檔案內容,而不是由屏幕輸出。
命令 |
功能描述 |
a\ |
新增, a 的后面可以接字串,在下一行出現 |
c\ |
替換 |
d |
刪除 |
i\ |
插入, i 的后面可以接字串 |
p |
打印 |
s |
查找並替換,例如 1,20s/old/new/g |
eg:
sed '2p' sed.txt 顯示第二行和所有數據
sed -n '2,3p' sed.txt 顯示第二和第三行
df -h | sed -n '1p' 接收命令結果數據
sed ‘2a liuyifei’sed.txt 在第二行后面添加數據
sed ‘4i fengjie \
canglaoshi’sed.txt 在第4行之前添加兩行數據
sed ‘2c this is replace’sed.txt 替換第二行數據
sed ‘s/it/edu360/g’ sed.txt 把sed.txt文件中的it替換為edu360,並輸出
sed -e '1s/1/34/g;3s/yangmi//g' sed.txt 同時進行多個替換
sed –i ‘s/it/edu360/g’ sed.txt 要想真正替換,需要使用-i參數
使用sed獲取機器的ip地址
ifconfig eth0 | grep 'inet addr'| sed 's/^.*addr://g' | sed 's/ Bcast.*$//g'
定時器
crontab 命令允許用戶提交、編輯或刪除相應的作業。每一個用戶都可以有一個crontab 文件來保存調度信息。可以使用它運行任意一個 s h e l l 腳本或某個命令。
crontab命令格式
作用:用於生成cron進程所需要的crontab文件
crontab的命令格式
# crontab -e
使用編輯器編輯當前的crontab文件。
crontab文件格式
minute hour day-of-month month-of-year day-of-week commands
分< >時< >日< >月< >星期< >要運行的命令 < >表示空格
其中
Minute 一小時中的哪一分鍾 [0~59]
hour 一天中的哪個小時 [0~23]
day-of-month 一月中的哪一天 [1~31]
month-of-year 一年中的哪一月 [1~12]
day-of-week 一周中的哪一天 [0~6] 0表示星期天
commands 執行的命令
書寫注意事項
1,全都不能為空,必須填入,不知道的值使用通配符*表示任何時間
2,每個時間字段都可以指定多個值,不連續的值用,間隔,連續的值用-間隔。
3,命令應該給出絕對路徑
4,用戶必須具有運行所對應的命令或程序的權限
如何使用crontab 運行多個任務:
方法1:在crontab -e 里 寫多個
輸入命令 crontab –e
敲回車
開始編寫任務:
方法2:把所有的任務,寫入到一個可執行的文件
再在crontab -e里面配置執行任務
分鍾 小時 天 月 星期 命令/腳本
示例:
eg:4點備份
0 4 * * *
eg:每周二,周五,下午6點 的計划任務
0 18 * * 2,5
eg:1到3月份,每周二周五,下午6點的計划任務
0 18 * 1-3 2,5
eg:周一到周五下午,5點半提醒學生15分鍾后關機
30 17 * * 1-5 /usr/bin/wall < /etc/issue
45 17 * * 1-5 /sbin/shutdown -h now
eg:學校的計划任務, 12點14點,檢查apache服務是否啟動
*/2 12-14 * 3-6,9-12 1-5
eg:再添加一個備份,把/etc目錄備份到/backup下,然后把錯誤的情況也記錄下來,正確的文件都丟到/dev/null下,看不見(相當於一個黑洞)
*/2 12-14 * 3-6,9-12 1-5 /bin/cp -r /etc /backup/etc.20170407 2> /backup/etc.bak.err
/dev/null */2表示每隔兩分鍾
eg:每月 1、1 0、2 2日的4:45運行/apps/bin目錄下的backup.sh
45 4 1,10,22 * * /apps/bin/backup.sh
eg:每周六、周日的 1 : 10運行一個find命令
10 1 * * 6,0 /bin/find -name "core" -exec rm {} \;
eg:在每天 18:00至23 :00之間每隔30分鍾運行/apps/bin目錄下的dbcheck.sh
0,30 18-23 * * * /apps/bin/dbcheck.sh
eg:每星期六的 11:00 pm運行/apps/bin目錄下的qtrend.sh
0 23 * * 6 /apps/bin/qtrend.sh