*Shell 是什麼 ?
任何發明都具備供用戶使用的界面。
UNIX
供用戶使用的界面就是
Shell(DOS
的
command
熟悉吧,但
UNIX
的要強大的多
)
。
Shell
爲用戶提供了輸入命令和參數並可獲得命令執行結果的環境。
爲了避免同的須要,
UNIX
提供了不一樣的
Shell
。如今的
UNIX
大部分都支持
BourneShell
,如下教程就以
BourneShell(Bsh)
爲例,一步步的領略
UNIX Shell
的強大功能,佔先其強大魅力,達到更方便靈活的管理、應用
UNIX
的目的。
1.UNIX
內核和
Shell
的交互方法
啓動
UNIX
時,程序
UNIX(
內核
)
將被調入計算機內存,並一直保留在內存中直到機器關閉。在引導過程當中,程序
init
將進入後臺運行一直到機器關閉。該程序查詢文件
/etc/inittab
,該文件列出了鏈接終端的各個端口及其特徵。當發現一個活動的終端時,
init
程序調用
getty
程序在終端上顯示
login
等登錄信息。
(username
和
passwd)
,在輸入密碼後,
getty
調用
login
進程,該進程根據文件
/etc/passwd
的內容來驗證用戶的身份。若用戶經過身份驗證,
login
進程
把用戶的
home
目錄設置成當前目錄並把控制交給一系列
setup
程序。
setup
程序能夠是指定的應用程序,一般
setup
程序
爲一個
Shell
程序,如
:/bin/sh
即
Bourne Shell
(
command
出來了,呵呵)。
獲得控制後,
Shell
程序讀取並執行文件
/etc/.profile
以及
.profile
。這兩個文件分別創建了系統範圍內的和
該用戶本身的工做環境。最後
Shell
顯示命令提示符,如
$
。
(
這是以
bsh
爲例,如果
csh,
爲
.cshrc,ksh
爲
.kshrc,bash
爲
.bashrc
等等
)
注
:(
不妨把
/etc/.profile
和
.profile
當作
DOS
的
autoexec.bat
或
config.sys
文件
)
當
shell
退出時,內核把控制交給
init
程序
,
該程序從新啓動自動登錄過程。有兩種方法使
shell
退出,一是用戶執行
exit
命令,二是
內核
(
例如
root
用
kill
命令
)
發出一個
kill
命令結束
shell
進程。
shell
退出後,內核回收用戶及程序使用的資源。
用戶登錄後,用戶命令同計算機交互的關係爲
:
命令進程
--->Shell
程序
--->UNIX
內核
--->
計算機硬件。當用戶輸入一個命令,如
$ls, Shell
將定位其可執行文件
/bin/ls
並把其傳遞給內核執行。內核產生一個新的子進程調用並執行
/bin/ls
。當程序執行完畢後,內核取消
該子進程並把控制交給其父進程,即
Shell
程序。例如執行
:
$ps
該命令將會列出用戶正在執行的進程,即
Shell
程序
(
下來詳細說說,別急如今
)
和
ps
程序。若執行
:
$sleep 10 &
$ps
其中第一條命令將產生一個在後臺執行的
sleep
子進程。
ps
命令執行時會顯示出該子進程。
每當用戶執行一條命令時,就會產生一個子進程。該子進程的執行與其父進程或
Shell
徹底無關,這樣可使
Shell
去作其餘工做。
(Shell
只是把用戶的意圖告訴內核,而後該幹嗎幹嗎
:))
如今
windows
有個計劃任務
(
在固定的時間,日期自動執行某任務
),
其實
UNIX
很早就有這個功能了,也就是所謂的
Shell
的自動執行。一些
UNIX
資源,如
cron
能夠自動執行
Shell
程序而無需用戶的參與,
(
這個功能好象在
/var/spool/crotab
目錄裏
)
。
Crontab
程序對於系統管理員來講是很是有用的。
Cron
服務用於計劃程序在特定時間(月、日、周、時、分)運行。咱們以
root
的
crontab
爲例。根用戶的
crontab
文件放在
/var/spool/crontab/root
中,其格式以下:
(1)
(2)
(3)
(4)
(5)
(6)
0
*
*
3
/usr/bin/updatedb
1.
分鐘
(0-60)
2.
小時
(0-23)
3.
日
(1-31)
4.
月
(1-12)
5.
星期
(1-7)
6.
所要運行的程序
2.Shell
的功能和特色
1>
命令行解釋
2>
使用保留字
3>
使用
Shell
元字符
(
通配符
)
4>
可處理程序命令
5>
使用輸入輸出重定向和管道
6>
維護一些變量
7>
運行環境控制
8>
支持
Shell
編程
對於命令行解釋就很少說了,就是在
shell
提示符
(
例如
:$,%,#
等
)
後輸入一行
unix
命令,
Shell
將接收用戶的輸入。
使用保留字
:Shell
有一些具備特殊意義的字,例如在
Shell
腳本中,
do,done,for
等字用來控制循環操做,
if,then
等控制條件操做。
保留字隨
Shell
環境的不一樣而不一樣。
通配符:
*
匹配任何位置
?
匹配單個字符
[]
匹配的字符範圍或列表
例如
:
$ls [a-c]*
將列出以
a-c
範圍內字符開頭的全部文件
$ls [a,m,t]*
將列出以
e,m
或
t
開頭的全部文件
程序命令
:當用戶輸入命令後,
Shell
讀取環境變量
$path(
通常在用戶本身的
.profile
中設置
)
,該變量包含了命令可執行文件可能存在的目錄列表。
shell
從這些目錄中尋找命令所對應的可執行文件,而後將該文件送給內核執行。
輸入輸出重定向及管道
:重定向的功能同
DOS
的重定向功能:
>
重定向輸出
<
重定向輸入
而管道符號,是
unix
功能強大的一個地方
,
符號是一條豎線
:|
,用法
: command 1 | command 2
他的功能是把第一個命令
command 1
執行的結果做爲
command 2
的輸入傳給
command 2
,例如
:
$ls -s|sort -nr|pg
該命令列出當前目錄中的全部文件,並把輸出送給
sort
命令做爲輸入,
sort
命令按數字遞減的順序把
ls
的輸出排序。而後把排序後的
內容傳送給
pg
命令,
pg
命令在顯示器上顯示
sort
命令排序後的內容。
維護變量
:
Shell
能夠維護一些變量。變量中存放一些數據供之後使用。用戶能夠用
=
給變量賦值,如
:
$lookup=/usr/mydir
該命令創建一個名爲
lookup
的變量並給其賦值
/usr/mydir,
之後用戶能夠在命令行中使用
lookup
來代替
/usr/mydir
,例如
:
$echo $lookup
結果顯示
:/usr/mydir
爲了使變量能被子進程使用
,
可用
exprot
命令,例如
:
$lookup=/usr/mydir
$export lookup
運行環境控制
:當用戶登錄啓動
shell
後,
shell
要爲用戶建立一個工做的環境,以下
:
1>
當
login
程序激活用戶
shell
後,將爲用戶創建環境變量。從
/etc/profile
和
.profile
文件中讀出,在這些文件中通常都用
$TERM
變量設置終端類型,用
$PATH
變量設置
Shell
尋找可執行文件的路徑。
2>
從
/etc/passwd
文件或命令行啓動
shell
時,用戶能夠給
shell
程序指定一些參數,例如
-x
,能夠在命令執行前顯示該命令及其參數。後面詳細介紹這些參數。
shell
編程
:本文主要介紹的內容。
shell
自己也是一種語言
(*
能夠先理解爲
unix
命令的組合,加上類
C
的條件,循環等程序控制語句
,
相似
dos
批處理,但要強大的多
),
用戶能夠
經過
shell
編程
(
腳本
,
文本文件
)
,完成特定的工做。
SHELL
變量
下面咱們詳細的介紹
Bourne Shell
的編程
:
自從貝爾實驗室設計了
Bourne Shell
。從那時起許多廠商根據不一樣的硬件平臺設計了許多版本得
unix
。但在衆多版本的
unix
中,
Bourne Shell
一直保持一致。
1>Bsh
的啓動:用戶在登錄後,系統根據文件
/etc/passwd
中有關該用戶的信息項啓動
Shell
。例如某用戶在
passwd
中
的信息項爲
:
ice_walk:!:411:103:Imsnow ,ice_walk:/home/ice_walk:/bin/bsh
則代表,用戶名是
ice_walk
等信息,在最後一項
/bin/bsh
代表用戶的
sh
環境類型是
bsh,
因而系統啓動之。在啓動或執行
(
包括下面咱們要講
的
shell
程序
--
腳本)過程當中可使用如下一些參數,咱們一一說明
:
-a
將全部變量輸出
-c string
從
string
中讀取命令
-e
使用非交互式模式
-f
禁止
shell
文件名產生
-h
定義
-i
交互式模式
-k
爲命令的執行設置選項
-n
讀取命令但不執行
-r
受限模式
-s
命令從標準輸入讀取
-t
執行一命令,而後退出
shell
-u
在替換時,使用未設置的變量將會出錯
-v
顯示
shell
的輸入行
-x
跟蹤模式,顯示執行的命令
許多模式能夠組合起來用
,
您能夠試試了,但
-ei
好象不行,你說
why
呢?
使用
set
能夠設置或取消
shell
的選項來改變
shell
環境。打開選項用
-,
關閉選項用
+,
多數
unix
容許打開或關閉
a
、
f
、
e
、
h
、
k
、
n
、
u
、
v
和
x
選項。若顯示
Shell
中已經設置的選項,執行
:
$echo $-
Bsh
中每一個用戶的
home
目錄下都有一個
.profile
文件,能夠修改該文件來修改
shell
環境。爲了增長一個可執行文件的路徑
(
例如
/ice_walk/bin)
,
能夠把下面代碼加入
.profile
中
PATH=$PATH:/ice_walk/bin;exprot PATH
.profile
中
shell
的環境變量意思以下
:
CDPATH
執行
cd
命令時使用的搜索路徑
HOME
用戶的
home
目錄
IFS
內部的域分割符,通常爲空格符、製表符、或換行符
MAIL
指定特定文件
(
信箱
)
的路徑,有
UNIX
郵件系統使用
PATH
尋找命令的搜索路徑
(
同
dos
的
config.sys
的
path)
PS1
主命令提示符,默認是
$
PS2
從命令提示符,默認是
>
TERM
使用終端類型
2>Bsh
裏特殊字符及其含義
在
Bsh
中有一組非字母字符。這些字符的用途分爲四類
:
做爲特殊變量名、產生文件名、數據或程序控制以及引用和逃逸字符控制。他們
可讓用戶在
Shell
中使用最少的代碼完成複雜的任務。
*> Shell
變量名使用的特殊字符
$#
傳送給命令
Shell
的參數序號
$-
在
Shell
啓動或使用
set
命令時提供選項
$?
上一條命令執行後返回的值
$$
當前
shell
的進程號
$!
上一個子進程的進程號
$@
全部的參數,每一個都用雙括號括起
$*
全部參數,用雙括號括起
$n
位置參數值,
n
表示位置
$0
當前
shell
名
*>
產生文件名的特殊字符
包括
*,?,[]
,上面講過,再也不多說。
*>
數據或程序控制使用的特殊字符
>(file)
輸出重定向到文件中
(
沒有文件則建立,有則覆蓋
)
>>(file)
輸出重定向到文件中
(
沒有則建立,有則追加到文件尾部
)
<(file)
輸入重定向到文件
;
命令分割符
|
管道符
&
後臺運行
(
例如
:sleep 10 &)
` `
命令替換,重定向一條命令的輸出做爲另外一命令的參數
*>
對於引用或逃逸的特殊字符
Bsh
用單引號
' '
和雙引號
將特殊字符或由空白分隔的字引用起來組成一個簡單的數據串
.
使用單引號和雙引號的區別是雙引號中的內容可進行參數和變量替換
.
逃逸字符也同樣
.
$echo $HOME $PATH
結果顯示
$/u/ice_walk/bin:/etc:/usr/bin
而
$echo '$HOME $PATH'
結果顯示
$HOME $PATH
shell
的逃逸符是一個
\\,
表示其後的字符不具備特殊的含義或不是
shell
的函數
$echo \\$HOME $PATH
結果顯
$$HOME /bin:/etc:/usr/bin:
3>Bsh
的變量
前面咱們在多個地方引用了變量
,
當
Shell
遇到一個
$
符時
(
沒有被引用或逃逸
)
,它將認爲其後爲一變量。不論該變量是環境變量仍是用戶自定義的變量,在命令行中變量名要被變量值替換。例如命令
:ls $HOME
將列出變量
HOME
對應目錄下的文件。
用戶能夠在命令行中的任何地方進行變量替換。包括命令名自己,例如:
$dir=ls
$$dir f*
將列出以
f
開頭的文件。
如今詳細的介紹下
Bsh
的變量。
Bsh
中有四類變量
:
用戶定義的變量、位置變量
(shell
參數
)
、預約義變量及環境變量。
用戶定義的變量:
用戶定義的變量由字母和下劃線組成,而且變量名的第一個字符不能爲數字
(0~9)
。與其餘
UNIX
名字同樣,變量名是大小寫敏感的。用戶能夠在命令行上用
=
給變量賦值,例如
:
$NAME=ice_walk
給變量
NAME
賦值爲
ice_walk,
在應用變量
NAME
的時候,在
NAME
前加
$
便可,前面已說,再也不廢話
(
別說我廢話多,關鍵是沒當過老師
:()
。能夠用變量和其餘字符組成新的字,例如
:
$SUN=sun
$echo ${SUN}day
在應用
shell
變量時候,能夠在變量名字兩邊
$
後面加上
{}
,以更加清楚的顯示給
shell,
哪一個是真正的變量,以實現字符串的合併等功能。
結果顯示
:sunday(
注意不能
echo $SUNday,
由於
SUNday
變量沒定義,讀者試下執行結果
)
用戶也能夠在命令行上同時對多個變量賦值,賦值語句之間用空格分開
:
$X=x Y=y
注意變量賦值是從右到左進行的
$X=$Y Y=y
X
的值是
y
$X=z Y=$Z
Y
的值是空
(
變量未賦值時,
shell
不報錯,而是賦值爲空
)
用戶可使用
unset <
變量
>
命令清除給變量賦的值
用戶使用變量時要在其前面加一
$
符,使變量名被變量值所替換。
Bsh
能夠進行變量的條件替換,即只有某種條件發生時才進行替換。替換條件放在一對大括號
{}
中,如
:
${variable: -value} variable
是一變量值,
value
是變量替換使用的默認值
$echo Hello $UNAME
結果顯示
:Hello
$echo Hello ${UNAME: -there}
結果顯示
:Hello there
$echo $UNAME
結果顯示
: (
空
)
$UNAME=John
$echo Hello ${UNAME: -there}
結果顯示
:Hello John
能夠看出,變量替換時將使用命令行中定義的默認值,但變量的值並無所以而改變。另一種替換的方法是不但使用默認值進行替換,並且將默認值賦給該變量。其形式以下
:
${variable:=value}
該形式在變量替換後同時把值
value
符給變量
variable
。
$echo Hello $UNAME
結果顯示
:Hello
$echo Hello ${UNAME:=there}
結果顯示
:Hello there
$echo $UNAME
結果顯示
:there
$UNAME=John
$echo Hello ${UNAME:-there}
結果顯示
:Hello John
變量替換的值也能夠是
` `
括起來的命令
:
$USERDIR={$Mydir: -`pwd`}
第三種變量的替換方法是隻有當變量已賦值時才用指定值替換形式
:
${variable: +value}
只有變量
variable
已賦值時,其值才用
value
替換,不然不進行任何替換,例如
:
$ERROPT=A
$echo ${ERROPT: +Error tracking is acitive}
結果顯示
:Error tracking is acitive
$ERROPT=
$echo ${ERROPT: +Error tracking is acitive}
結果顯示
: (
空
)
咱們還可使用錯誤檢查的條件進行變量替換
:
${variable:?message}
當變量
variable
已設置時,正常替換。不然消息
message
將送到標準錯誤輸出
(
若此替換出如今
shell
程序中
,
那麼該程序將終止
)
。 例如:
$UNAME=
$echo $ {UNAME:?UNAME HAS NOT BEEN SET}
結果顯示
:UNAME HAS NOT BEEN SET
$UNAME=Stephanie
$echo $ {UNAME:?UNAME HAS NOT BEEN SET}
結果顯示
:Stephanie
當沒有指定
message
時,
shell
將顯示一條默認的消息,例如
:
$UNAME=
$echo $ {UNAME:?}
結果顯示
:sh:UNAME:parameter null or not set
4>
位置變量或
Shell
參數
在
shell
解釋用戶的命令時,將把命令行的第一個字做爲命令,而其餘的字做爲參數。當命令對應的可執行文件爲
Shell
程序時,這些參數將做爲位置變量傳送給該程序。第一個參數記爲
$1,
第二個爲
$2....
第九個爲
$9
。其中
1
到
9
是真正的參數名,
$
符只是用來標識變量的替換。
位置變量
$0
指命令對應的可執行文件名。在後面將詳細介紹位置變量。
1.
只讀變量
用戶將變量賦值後,爲了防止之後對該變量的修改,能夠用如下命令將該變量設置爲只讀變量:
readonly variable
2.export
命令
shell
執行一個程序時,首先爲該程序創建一個新的執行環境,稱爲子
shell
。在
Bourne Shell
中變量都是局部的,即他們只在建立他們的
Shell
中有意義。用戶能夠用
export
命令讓變量被其餘子
Shell
識別。但某用戶的變量是無法讓其餘用戶使用的。
當用戶啓動一個新
shell
時
,
該
shell
將使用默認的提示符。由於賦給變量
PS1
的值只在當前
shell
中有效。爲了讓子
Shell
使用當前
Shell
中定義的提示符號,可使用
export
命令:
$PS1=Enter command:
Enter command:export PS1
Enter command:sh
Enter command:
此時變量
PS1
變成了全局變量。它能夠被其子
Shell
使用。當變量被設置成全局的之後,將一直保持有效直到用戶退出該變量所在的
Shell
。用戶能夠在文件
.profile
中給一個變量永久賦值。詳見規範
Shell
。
基本語句
從本節起,咱們將詳細介紹
Shell
程序設計的基本知識,經過編寫
Shell
腳本,用戶能夠根據本身的須要有條件的或者重複的執行命令。經過
Shell
程序,能夠把單個的
UNIX
命令組合成一個徹底實用的工具,完成用戶的任務。
1>
什麼是
Shell
程序
當用戶在
UNIX Shell
中輸入了一條複雜的命令,如
:
$ls -R /|greo myname |pg
咱們能夠稱用戶在對
Shell
編程,當把這條語句寫在一個文件裏,而且符給該文件可執行權限,那麼該文件就是咱們傳統上說的
Shell
程序。
2>
簡單的
Shell
程序
假設用戶天天使用下述命令備份本身的數據文件
:
$cd /usr/icewalk;ls * |cpio -o > /dev/fd0
咱們能夠把它寫在一個文件,如
:ba.sh
中
:
$cat >ba.sh
cd /usr/icewalk
ls * |cpio -o > /dev/fd0
^D
(ctrl_d)
程序
ba.sh
就是
Shell
腳本,用戶能夠用
vi
或其餘編輯工具編寫更復雜的腳本。
此時用戶備份文件只須要執行
Shell
程序
ba.sh,
執行時需在當前
Shell
中建立一個子
Shell:
$sh ba.sh
程序
sh
與用戶登錄時執行的
Bourne Shell
相同,但當
Sh
命令帶參數
ba.sh
後,它將再也不是一個交互式的
Shell
,而是直接從文件
ba.sh
中讀取命令。
執行
ba.sh
中命令的另外一方法是給文件
ba.sh
執行權限:
$chmod +x ba.sh
此時,用戶能夠輸入文件名
ba.sh
作爲一個命令來備份本身的數據,須要注意的是,用這種方法執行命令的時候,文件
ba.sh
必須存在於環境變量
$PATH
所指定的路徑上