*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
所指定的路径上