资源描述
Shell: 是一个独立于 OS 的应用程序,是一个具有交互性的命令行解释器。
1、Shell 的作用: 解释键入的命令以及执行的一些特定的功能,并传到内核执行。
2、Shell 的功能:
- 命令的搜索与执行
- 变量的值的替换
- 命令的替换
- 文件名的补齐
- 控制 I/O 重定向和 Pipe
- 提供解释性的编程接口(包括测试、分支和循环)
3、常用的 Shell:
- Bourne Shell(/usr/bin/sh)
- C Shell(/usr/bin/csh)
- Korn Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
- Restricted Bourne Shell(/usr/bin/rsh)
- Restricted Korn Shell(/usr/bin/rksh)
[注]
(1)、某些系统有自带的 Shell,比如 SCO UNIX 系统有 SCO Shell(/usr/bin/scosh)。
(2)、使用限制版 Shell 的用户不能进行的操作:
- 修改目录
- 重设 PATH 环境变量
- 在路径中使用 /
- 重定向输出
è 别名化:主要用于方便地输入长路径名。
$ alias [name [=string]] # Aliasing
其中: name -- 命令的别名, string -- 原命令(如果有空格,用 ‘ ’ 括起来)。
$ alias # 显示当前定义的所有别名
$ alias name # 列出某特定别名的值
$ unalias name # 关闭别名
[例]别名的使用:
$ alias go = 'cd '
$ alias there = /home/cheyenne/programs/shell/pgs_en_c/server.c
$ go there ; pwd
--> 命令历史:
1、最早由 C Shell(BSD UNIX)提出。
2、Korn Shell 下的 history 命令:
- 缺省显示最近输入的16个命令
- 每行用命令号开头
CODE
$ history -n # 显示最后 n 个命令
$ history a z # 显示从第 a 条命令到第 z 条命令
3、
HISTSIZE 参数:定义可以访问历史命令的数据(缺省:128)。
HISTFILE 参数:指定存储已输入命令的文本文件(缺省: .sh_history)。
4、重新输入命令:
$ r n # n 是命令号或一个命令的首字母(执行以该字母开头的最近的命令)
用户环境:
1、环境描述的是会话过程:
- 主目录的路径名
- 存放 e-mail 的目录
- 工作的时区
- 登录的身份
- Shell 搜索命令时的路径
- 终端类型
- 应用程序所依赖的其它东西
2、常见的环境变量:
- TERM, COLUMNS 和 LINES 描述终端
- HOME 用户主目录
- PATH 搜索命令的地点列表
- LOGNAME 登录用户名
- env 和 HISTFILE 专用的 POSIX Shell 变量
- DISPLAY 专用的 X Window 变量
3、设定 Shell 变量:
$ name=value
[规定]变量名以字母开头,可以包含字母、数字和下划线。
4、PATH 变量:和 DOS 里的 PATH 变量是一样的,代表 Shell 搜索命令的一系列目录。
5、TERM 变量:描述使用的终端。
$ TERM=70092
$ tset # 将 TERM 值设置终端
[注]可以查看 /usr/lib/terminfo 下的子目录
6、常见的变量及其值:
- EDITOR=/usr/bin/vi # 用 vi 作为行编辑命令
- ENV=$HOME/.shrc # 在启动 Shell 时执行 $HOME/.shrc
- HOME=/home/cheyenne # 用户主目录
- FCEDIT=/usr/bin/vi # 对历史命令行启用 vi 编辑进程
- ~ # 在 Korn Shell 和 POSIX Shell 中代表用户主目录
- HISTFILE=$HOME/.sh_history
- LOGNAME=cheyenne
- MAIL=/var/mail/cheyenne # 系统信箱
- OLDPWD=/home # 前一个目录的位置
- PATH=……
- PS1='[!]$' # 设置提示符
- PWD=/home/cheyenne/programs/shell # 显示当前工作目录(相当于 DOS 中的 CD 命令)
- SHELL=/usr/bin/sh
- TERM=2392a # 用命令 eval `test -s -Q -h` 在启动时,系统读取 /etc/ttytype 文件,用里面的信息正确设置终端。
- TMOUT=300 # 在指定的时间(秒)内没有键入命令,Shell 会终止或超时。
- TZ=EST5EDT # 工作时区
è 登录:
1、显示文件 /etc/issue 的内容
2、发出 login 提示符
3、运行 login
4、核对帐号和密码
5、将用户置于主目录
6、运行用户的 Shell
7、运行 /etc/profile(Bourne Shell 和 Korn Shell)或 /etc/csh.login(C Shell)
8、运行用户主目录中的 .profile 或 .login
9、执行主目录中的 .kshrc 文件
10、显示 Shell 提示符
[注] /etc/profile 文件搭建起系统每个用户的基本环境
运行 Shell --> 从 /etc/profile 系统命令文件中读出命令 --> 读取 $HOME/.profile 文件(细化环境以适应用户的要求)
用 CDE 登录:
CDE 通常不使用 /etc/profile、$HOME/.profile 和 $HOME/.login 这几个登录脚本。
但可以强迫执行 $HOME/.profile(sh 或 ksh)或 $HOME/.login(csh)。
方法是在 .dtprofile 中设置: DTSOURCEPROFILE=true
Shell 启动文件:
- Bourne Shell(/usr/bin/sh): $HOME/.profile
- Korn Shell(/usr/bin/ksh): $HOME/.profile,$HOME/.kshrc
- C Shell(/usr/bin/csh): $HOME/.login,$HOME/.cshrc
1、普通用户没有 /etc/profile 文件的写权限。
2、Korn Shell 有一个可选的配置文件 .kshrc,它不仅在启动时被读取,在每次启动一个新的 Shell 时都被读取。要使用这个文件,在 .profile 文件里加入:
ENV=~/.kshrc
export ENV
3、可以在 .profile 中加入 exec 命令: exec app,作用是启动用户的应用程序,但是无法看到 Shell 提示符,应用程序执行完毕后,退出系统。
4、以 C Shell 登录时,在起始目录查找 .login 文件。如果找到,出现提示符前执行这个文件里面的命令。如果用户还定义了 .cshrc 文件,出现提示符前也执行这个文件里的命令
whereis 命令:
$ whereis [-b|-m|-s] command # 搜索指定目录以判断特定的命令是否存在
UNIX 系统主要在 /sbin、/usr/bin、/usr/local/bin 和 /usr/contrib/bin 下存放命令,whereis 命令搜索这些目录和其它目录,以判断命令是否存在。
[NOTE]
1、许多用户在主目录下设有自己的 bin 目录,whereis 不搜索这些目录。
2、whereis 可以提供一个途径定位命令文件和定位命令在手册中的位置。
3、whereis 命令接受单个参数 —— 命令名,它返回该命令可执行代码的位置及其在手册中的位置。
4、若要修改 whereis 搜索的目录列表,用 -b、-m、-s ,使搜索相应的限制在二进制代码、手册或源代码的范围内。
[注]whereis 的搜索目录:
CODE
/usr/src/*
/usr/bin
/usr/share/man/*
/usr/local/games
/usr/contrib/man/*
/usr/contrib/include
/usr/local/man/$LANG/*
/usr/sbin
/usr/lbin
/usr/local/man/*
/usr/local/include
/usr/contrib/bin
/usr/contrib/lib
/usr/contrib/man/$LANG/*
/sbin
/usr/ccs/bin
/usr/local/bin
/usr/local/lib
/usr/contrib/games
/usr/share/man/$LANG/*
Shell 的高级特性:
1、在 Shell 中,有三种替换功能,可以加快对命令行的输入和执行:
- 变量替换
- 命令替换
- 波浪号替换
2、Shell 变量存储机制:
(1)、在 Shell 中,有两块内存存储 Shell 变量:本地数据区和用户环境区。
- 定义新变量:从本地数据区分配内存存储该变量。在这个区域的变量归当前 Shell 所有。任何后来启动的子进程都不能访问这些本地变量。
- 在登录进程中系统定义一些特殊的 Shell 变量,其中的很多被存储在用户环境区。
- 从本地数据区移动到用户环境区的变量可以被子进程访问。
(2)、$ env # 显示当前环境的所有变量
3、给变量赋值: $ name=value
- 用户定义一个新变量:被存储在本地数据区中。
- 将一个新值分配给一个已经存在的环境变量:新值取代旧值。
4、变量替换: $ name # Directs the shell to perform variable substitution.
(1)、每个被定义的变量有一个值与其相关,变量名前加 $ 符号时,Shell 用值来替换这个参数。这个过程称为变量替换。这个过程在 Shell 运行命令行命令之前执行。
(2)、Shell 将命令行中所有需要替换的变量做替换之后才执行该命令。
(3)、变量可以代表命令、命令的参数或整行命令行。
(4)、$ echo $name # 显示变量的当前值
[例]$ PATH=$PATH:$HOME
$ echo $PATH
$ file_name=$HOME/programs/pgs_en_c/server.cpp
$ more $file_name
(5)、有两个变量:
$ file1=this
$ file2=that
$ echo $file1and$file2 # Shell 会认为是查找变量 file1and 和变量 file2
sh: file1and: parameter not set
$ echo ${file1}and$file2 # 解决方案:用大括号界定变量名与其周围的文本
thisandthat
(6)、用绝对路径名定义一个变量的值,通过使用该变量,可以在文件系统的任何位置访问目标文件或目录。
(7)、引号的作用:
$ cheyenne=2
$ echo cheyenne # 在屏幕上显示 cheyenne
$ echo $cheyenne # 在屏幕上显示 2
$ echo “$cheyenne” # 在屏幕上显示 2
$ echo '$cheyenne' # 在屏幕上显示 $cheyenne
5、命令替换:同一个命令行中用一个命令的输出结果替换该命令。
$ `command`
常用于将一个命令的输出结果分配给一个变量,然后引用或控制该变量。
[例]$ banner data
$ banner `data`
6、波浪号替换:
- 若一个词以 ~ 开头,这个词会扩展这个波浪号。
- 只能扩展位于单词开头的波浪号(/~home/cheyenne 不能扩展其中的波浪号)。
- 单独的一个 ~ 或在 / 之前的 ~ : 用 $HOME 取代~。
- ~+ : 用 $PWD 取代 ~(cd 命令将重设 PWD 的值)。
- ~- : 用 $OLDPWD 取代 ~(cd 命令将重设 OLDPWD 的值)。
- 若 ~ 后面紧跟几个字符,然后接一个 /,Shell 会核对这几个字符是否与某系统用户名匹配,若匹配,就用该用户名取代~。
7、显示变量的值:
$ env # 显示在用户环境中定义的所有的变量的值
$ set # 显示在本地数据区和用户环境中当前定义的所有变量的值
$ unset # 删除指定变量的当前值(该变量的值将被指定为 NULL,此值有效)
8、将本地变量转移到用户环境中:
$ export variable
$ export varibale=value # 给变量赋值并转移
$ export # 显示所有被输出变量的名字及其值
9、向应用程序传递变量:
(1)、登录后,Shell 程序被载入内核执行。当在提示符下输入一个应用程序(或命令)的名字后,会创建一个子进程,并执行以下程序:
- fork 程序:复制 Shell 进程(包括程序代码、环境数据区和本地数据区)。
- exec 程序:将子进程的代码及本地数据区替换为请求执行的应用程序的代码及本地数据区。
- 执行请求的应用程序后,exec 命令结束。
(2)、执行子进程时,Shell(父进程)会转入睡眠状态,等候子进程结束。一旦子进程结束,它将释放占用的内存,唤醒父进程,这个父进程时刻准备接受另一个命令执行请求。
(3)、本地变量与环境变量:
- 定义新变量:此变量会被存储在与定义该变量的进程有关的本地数据区中。
- 若要使任何一个子进程都能访问这个变量,必须用 export 命令将其导出到用户环境中。
- 一旦此变量处于用户环境中,后来运行的所有子进程都可以访问此变量(用户环境的内容向每一个子进程广播)。
- 父 Shell 的环境变量不会被子进程修改。
10、监控进程:
$ ps [-f] # 显示当前运行(或处于睡眠状态)进程的信息
包括 PID 及 PPID(PID:进程号,PPID:父进程号)。
关于文件名:
1、文件名生成的字符集:
? 匹配任意单个字符(除用点开头的文件外)
[] 从将被匹配的字符里分类(除用点开头的文件外)
* 匹配零字符或更多的字符集(除用点开头的文件外)
2、点文件:
以点开头的文件在文件生成字符集里通常是隐藏的,文件名生成字符集永远也不会生成以点开头的文件名称。
3、三个通配符:
CODE
[例] $ ls -a
. .. .zz 1G 2G 7G 15G Ant Cat Dog abc abcdef ba cyz
$ echo [abc]?? # echo abc cyz
$ echo [1-9][A-Z] # echo 1G 2G 7G
$ echo [!A-Z]?? # echo 15G abc cyz
[注]叹号的作用是“非”的意思
引用:避免或删掉带有特殊意义的指定字符。
1、引用字符: \ ‘ “单引号本身不能被引用
2、\:删除下一个特殊字符的意义
反斜线总是屏蔽掉它后面一个字符的特殊意义(无论后面是什么字符)
3、’:屏蔽掉所有包含在其中间的字符的特殊意义
4、”:和单引号功能一样,但允许使用变量替换($)和命令替换(`)
如果要显示 $ 和 `,用 \ 来屏蔽。
[例]
CODE
$ color='red white and blue'
$ echo the value of \$color is $color
the value of $color is red white and blue
$ echo 'the value of \$color is $color'
the value of \$color is $color
[注]所有引用机制只能在单行命令中使用
Shell 编程概述:
1、Shell 程序(或叫 Shell 脚本):
- Shell 程序是按照一定的规则包含 UNIX 系统命令的文件。
- 要执行 Shell 程序,文件的权限至少是 r-x。
- 执行时,直接键入文件名。
- 可以传递给程序的数据:环境变量,命令行变量和用户输入的变量(read 命令)。
2、编程注意事项:
- 建议加注释(# 后面的内容为注释)。
- 不要生成文件名为 test 的 Shell 程序(test 命令是系统用于建立 Shell 命令的命令)。
- export 命令的使用(本地变量 --> 环境变量)。
- 子程序不能修改它上一级进程的环境变量。即使它对这个环境变量再次赋值,但在它的上一级进程里将不会受到影响。
3、Shell 程序中的参数:
$ sh_program arg1 arg2 … argX
$0 $1 $2 … $x
- 作用:主要用于在应用程序中互相传递数据。
- $0,$1,…,$9,${10},${11},…
- $0 代表命令名(程序的名字)。
特殊的 Shell 变量:
1、希望允许用户键入带有个数不定的参数,无论几个,程序都能正常运行。
2、 # 和 * :
$# -- 键入的命令行参数的个数
$* -- 访问整个命令行参数列表(不包括 $0)
3、若将整个参数串传递给一个命令时,这个命令必须支持多重参数。
[例]
CODE
# 此文件名为 example_01
echo "there are $# command-line arguments."
echo "they are $*."
echo "the 1st command-line argument is $1."
--------------------------------------------------------------
保存文件后执行以下命令:
$ chmod u+x example_01
$ example_01 cheyenne feming rayi nolwenn old_farmer
--------------------------------------------------------------
运行结果:
there are 5 command-line arguments.
they are cheyenne feming rayi nolwenn old_farmer.
the 1st command-line argument is cheyenne.
shift 命令:
1、格式: shift [n]
重新指定命令行参数的位置属性,允许用户通过命令行参数增加位置参数。
2、所有在 $* 字符里的参数左移 n 个位置,在 $# 里的递减 n 个。
3、缺省的 n 值为1。
4、对于参数0,shift 命令不起作用。
5、主要作用:
- 访问一些组中的位置属性参数(比如一系列的 x,y 坐标)
- 从一个命令行中去掉命令选项(比如选项在参数之前)
[注意]做一次 shift 操作,命令行中被移动的参数就会相应的丢失。若还想在以后的程序中使用这些参数,必须要在 shift 操作前保存。
ksh中的串编辑命令:
${variable#pattern} 删除匹配variable值头部的pattern的最短部分,返回剩余部分。
${variable##pattern} 删除匹配variable值头部的pattern的最长部分,返回剩余部分。
${variable%pattern} 删除匹配variable值尾部的pattern的最短部分,返回剩余部分。
${variable%%pattern} 删除匹配variable值尾部的pattern的最短部分,返回剩余部分。
其中,pattern可以是文件名通配符。
例如:
CODE
var=/home/sailing/programs/shell/e.f.g
${var} ====> /home/sailing/programs/shell/e.f.g
${var#/*/} ====> sailing/programs/shell/e.f.g
${var##/*/} ====> e.f.g
${var%.*} ====> /home/sailing/programs/shell/e.f
${var%%.*} ====> /home/sailing/programs/shell/e
${var%%/*/} ====> /home/sailing/programs/shell/e.f.g
${var%%/*} ====>
${var%/sailing*} ====> /home
${var%%/sailing*} ====> /home
- 用通配符匹配所有圆点文件:
在Bourne Shell,Korn Shell和bash中,可以用 .[!.]* 来匹配所有的以圆点开头的文件。
在tcsh中,可以用 .[^.]* 来匹配。
解决办法:通过shell设置文件。
CODE
dots=".[`echo \\\\001--0-\\\\0177`]*" # sh, ksh, bash
set dots=".[`echo Y--0-Z | tr YZ \\001\\117`]" # csh, tcsh
- ls命令技巧:
-t选项:根据文件的修改时间(ctime)来进行分类,先列出新的文件。
-u选项:显示文件的最后访问时间(atime),但是必须和-t或-l一起使用(单独的 ls -u 命令不起作用)。
-C选项:沿列向下而不是横向排列文件。
-A选项:同-a选项(列出所有文件),但是不包括.和..目录。
-L选项:列出这个链接指向的文件而不是链接本身。
- 不能访问一个文件?====>寻找文件名中的空格:
例如:
CODE
$ls
project exefiles tools
$cat project
cat: project: No such file or directory
可以试一下这个命令:
CODE
$ls -l | cat -v -t -e
total 89$
-rw-rw-rw- 1 sailing 28 Jan 7 10:00 project $
-rw-r--r-- 1 root 25179 Mar 2 15:00 exefiles$
cat命令的-e选项用一个$来标志行的末尾。project后面的$并没有紧跟文件名,这说明这个文件名是以一个空格结尾的。可以把它改名:
CODE
$mv 'project ' project
ls命令有个-q选项,把空格、TAB等空白字符显示为?。
- 显示文件名中的非打印字符:
例如:
CODE
$ls
ab??cd # 这表示在ab和cd之间有两个非打印字符
若想删除或重命名该文件,可以使用通配符,如 ab??cd。
[注意]有很多时候,可能会生成许多奇怪的文件名,ls命令显示它们是都是以????开始。这时,许多新手会天真地输入 rm ????*……
可以使用ls命令的-b选项来打印出任何非打印字符的八进制值(前加\)。
CODE
$ls -b
ab\013\014cd
- 巧设文件权限:
在对权限进行测试时,系统会依次检查各个组。若用户权限被拒绝,UNIX就不会再检查下一个组了。那么考虑这样一个情况,某个文件由用户sailing所有,位于组guests中,且有权限-----xrwx(八进制的017)。这会产生这样的结果:用户sailing自己不能使用该文件,组guests中的任何用户都可以执行该程序,且除了sailing和guests之外的任何人都能读、写和执行该程序。
这不是很常见的设置,但可以用类似的机制来拒绝一组用户访问或使用某个文件。
====> 假设用户在一台计算机上工作,其中有一些私人的、“客人”不能使用的文件。在该机器上工作的其他人应具有访问权。那么,可以把这些文件放到一个名叫deny的组所拥有的目录中,然后用chmod来拒绝对该组的权限:
CODE
#chmod 705 /dir
#ls -lgd /dir
drwx---r-x 2 root deny 512 Dec 11 12:00 /dir
- 从另一个用户的终端来清除你的屏幕(主要是为了保护显示器):
首先从另一个终端登录或者su到自己的帐号,然后:
CODE
$who | grep sailing
sailing ttyp3 Jan 1 10:00
$clear > /dev/ttyp3
若是在一个不同类型的终端上,那么应先临时设置TERM环境变量。
- tail命令:
CODE
$tail -n #显示最后n行
$tail +n #抛弃前面的n-1行,给出第n行和它后面的所有内容。
$tail -nb #显示文件的最后n块(n*512个字节)的内容。
$tail -r #以相反的顺序显示文件(从最后一行开始)
- wc命令的技巧:
CODE
$expr `wc -w < file1` - `wc -w < file2` #比较file1中的单词比file2中的多多少
- tr命令的-d和-s选项:
CODE
$tr -d ",.!?;:'"'"`' < file #从输入中删除所有在字符串中指定的一个或多个字符
$tr -s " " " " < file #删除第二个参数中多次连续出现的相同字符
- sort排序:
CODE
$sort -f #不区分大写字母和小写字母
$sort -nb +0 #忽略开始的空格(必须指定开始字段,即0)
UNIX对数字排序时是把前面额外加有空格的数字排在前面,用上面的命令可以解决这个麻烦。而sort -n命令则不行。
- Bourne Shell的冒号操作符:
1、代替UNIX的true命令来做一个无限while循环的条件:
CODE
while :
do commands
done
2、在if中使用else,但又要使then为空(什么都不干)时:
CODE
if condition
then :
else commands
fi
3、有的Bourne shell版本没有真正的#注释符,可以用冒号来伪装(最好使用引号,比较安全):
CODE
: 'written by sailing'
4、可用于像${var?}或${var=default}这样的参数替换:
CODE
: ${USER?} ${HOME?} #在USER或HOME变量没有设置时显示一个错误并退出
展开阅读全文