[转帖]unix-like系统的初步知识_VMware, Unix及操作系统讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  VMware, Unix及操作系统讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4095 | 回复: 0   主题: [转帖]unix-like系统的初步知识        下一篇 
ilikeorcl
注册用户
等级:中尉
经验:431
发帖:32
精华:1
注册:2012-12-17
状态:离线
发送短消息息给ilikeorcl 加好友    发送短消息息给ilikeorcl 发消息
发表于: IP:您无权察看 2012-12-21 10:56:19 | [全部帖] [楼主帖] 楼主

unix-like系统的初步知识

Shell承担着解释用户在CLI方式下所输入的命令的重要任务。当用户输入一个概念V的表达(即命令名)之后,Shell如何去找到系统中关于概念V的实现(即用来实现命令的程序)的呢?

Shell的做法,通常分为两个步骤:

1)判断用户的输入,是否为Shell的内置命令(即这样的命令是Shell的一部分,这类似于Microsoft DOS中的COMMAND.COM所提供的内部命令)。若判断为是,则执行;若判断为否,则:

2)在PATH环境变量所提供的路径(目录名)中,逐个路径地去寻找符合输入的命令。若找到,则执行;若找不到,则反馈“Command not found.”信息,即报错。

当然,如果用户显式地、完整地向Shell输入了概念V的实现(即可执行程序)所处的位置(即完整的路径/目录名称),那么Shell将直接执行那个可执行程序。

Microsoft DOS不同的是,UNIX-like系统不会认为用户的当前工作目录是PATH变量理所应当的一部分,也就是说,它不会在当前工作目录(与PATH所提供的目录不同)中寻找概念V的实现。

如果要执行当前工作目录中的可执行文件,应该使用这样的命令形式:

代码:

./foo


即:在可执行文件名的前面,顶上“./”(一个小数点加一个正斜杠)—— 这有强调当前工作目录的意味,这是出于对系统安全考虑的强制规定。

通过学习上面的知识,我们可以理解这麽一个技巧:

我们可以特地地将一些专门的路径(某些经常要用到的程序所处的位置),放置到PATH环境变量中,这样我们就不必每次输入完整的路径或切换工作目录了。

更新一个环境变量的实际的值,在csh/tcsh这样的Shell中,应当使用命令:

代码:

setenv VARNAME value


而在sh/bash这样的Shell中,应当使用命令:

代码:

export VARNAME=”value”


请注意上述二者在命令名、等号、双引号等方面的区别。

举个例子。如果我们希望我们的家目录成为PATH环境变量的一部分,那么,在csh/tcsh下,就可以使用这样的命令:

代码:

setenv PATH $PATH\:$HOME


请注意,在这个命令中,PATH环境变量中用来黏合路径用的“:”被写成了“\:”,这是因为,如果csh看到了一个单独的“:”紧跟在字符串后面,会将它解读为一个Built-In Command(内置命令)从而导致反馈“Bad: modifier in $ ($)”即第二个“$”解读错误,所以,为了让csh能在概念A的表达中正确地解读到一个“:”,我们就必须在“:”前面顶上一个“\” —— 这称为转义序列机制,学过C语言的学员,对此一定不会感到陌生。又如,我们希望系统反馈这麽一行字符:

代码:

$SHELL


那么我们可以使用命令:

代码:

echo \$SHELL


除了利用转义序列规避csh对概念A的表示解读失败,我们还可以使用命令:

代码:

setenv PATH ${PATH}:$HOME


实现相同的效果 —— 可见,一对花括号可以拦阻csh将单独的“:”与之前的字符串相黏合,从而规避将其解读为一个命令。

我们使用命令:

代码:

w

可以观察到当前整个系统上,有哪几位用户登录,他们分别从那个终端接入的。比如,反馈是这样的:

代码:

USER TTY FROM LOGIN@ IDLE WHAT
root v0 - 3:31PM 2 -csh (csh)


USER一栏给出了用户名;TTY一栏给出了该用户所接驳的终端名称;FROM一栏给出了该用户的登录地点(一般远程登录者以网络地址如IP地址形式给出);LOGIN@一栏给出了该用户的(最近一次)登录时刻;IDLE一栏给出了该用户的发呆时间(即从该用户最后一次敲键盘至当前时刻所间隔的分钟数);WHAT一栏给出了该用户当前的正在干什么(即当前的进程名及其参数)。

Shell有一种必需的本领,即向它所启动的程序提供Stdio(标准I/O)环境。标准I/O环境,这个抽象的概念是什么意思呢?

我们知道,一个概念V的实现(命令程序)是由Shell找到并启动的。当Shell启动一个程序之后,就会向这个程序提供三个File Handle(文件句柄),这三个文件句柄即构成了属于每个程序自己的标准I/O环境,它们分别是:

1stdin —— 标准输入,也叫“FD0FDFile Descriptor的缩写,意同File Handle,这是一种关于字符的Input Stream(输入流),通常,这个流的源头,就是我们手头的键盘。

2stdout —— 标准输出,“FD1”,这是一种关于字符的Output Stream,通常,这个流的出口,就是我们面前的终端屏幕(即/dev/ttyvx文件,因此,该流以文件句柄的形式存在),当然你也可以使用前述的重定向方法将改流转向输出其他文件(犹如黄河改道,从江苏省流向黄海)。

3stderr —— 标准错误信息输出,“FD2”,从流与流的输出形式上说,它与stdout一致,只是程序主体会选择性令错误信息经由这个途径流出。为什么要这么做?这其实是一个很巧妙、很合理的设计,目的在于:使程序的正常输出(它的本分工作的结果)与它在遇到错误时所报出的错误信息可以分开,泾渭分明,这样,那些期望攫获该程序正常结果的另一个程序,就可以仅仅收到期望的信息,而不受报错信息的干扰。而且,我们可以通过重定向机制,将stdoutstderr流分别导向到不同的文件中去,具体方法是:

代码:

(foo > bar) >& qux


foo程序的stdoutFD1流写入文件bar,且将foo程序的stderrFD2流写入文件qux。※由于FreeBSD的默认Shelltcsh并没有提供单纯而直接的方法,将stdout流与stderr流分别重定向,所以,tsch的用户必须使用上述技巧实现stdoutstderr的分别重定向。

而对于GNU/Linux普遍采用的bash,分流的方法则十分清晰明了:

代码:

foo > bar



代码:

foo 1> bar


是将foo程序的stdoutFD1流写入文件bar


代码:

foo 2> qux


是将foo程序的stderrFD2流写入文件qux

※请注意,数字“1”“2”都必须紧贴“>”,否则数字将被视作概念O的表达。

所以,我们要引入一个新的范式:

STDIN-PROG-STDOUT(-STDERR)


简写作:

I-P-O(-E)


这个范式跟之前(关于用户与系统之间关系)的V(O,A)范式不同,它是用来概念化为PROGrams(程序)与Shell为其所提供的标准I/O环境及其要素的。在每个要素之间,川行的是数据流,数据流透过Stdio句柄被接纳或释出。

现在,我们考虑一个问题:既然程序可以由Shell为其创建的stdin(源头通常是键盘)来获取输入信息(流),那么,是否可以选择其他的信息输入源头呢?比如bar程序不再从用户的键盘获取输入信息,而是以foo的输出作为自己的输入源头,即:foo程序的stdout流与bar程序的stdin对接(信息如水流自上而下地行进)?这样的对接完全是可以实现的,那就是利用Shell提供的管道机制!命令的形式如下:

代码:

foo | bar


我们回到一开始的例子:

代码:

ls | grep "^foo.*"


ls命令程序的输出信息是当前一级目录里的所有文件,这样的信息应该是:

代码:

bar1
bar2
bar3
……
bar9998
bar9999
foo1
foo2
foo3
……
foo9998
foo9999


一共20,000行。

※寻常状况下,我们所看到的ls命令(无参数)的反馈,各个文件名都是按照表格式样排列呈现的,但当这些信息成为stdio流的时候,其实是按照呈现的,例如我们使用命令:

代码:ls | less

就可以看到文件名以排列呈现。less命令是一个用来查看文本类型文件的内容的程序,使用时按[PageUp][PageDown]键可以实现翻页,按[↑][↓]键可以实现滚动,按[q]键盘退出程序。

20,000行的信息并没有被反馈到终端屏幕(即/dev/ttyvx文件)上,而是经由管道哺馈给(流向)了管道符后面的grep命令程序,即这10,000行信息成为了grep命令的stdin的内容。

grep命令程序,全称是“Global Regular Expression Print”,这个全称揭示了这个工具的特性:“Global”指它的工作对象是全局也就是全部的行,“Regular Expression”就是正则表达式“Print”就是打印,统合起来说,就是:在stdin的全部行中,找到跟给定正则表达式匹配的内容,并将该内容所在的行打印出来(该内容本身通常会被高亮凸显)。

说到正则表达式(简称RegExp),它又是一个极具UNIX STYLE的超级武器。RegExp的内容极为广泛与庞杂,若要精通它,恐怕要跟精通C语言的难度相当。许多讲述RegExp的教材的作者自己就对它一知半解、不得真要,所以写出来的教材也让学生看得云里雾里、稀里糊涂,更是完全无法发挥这套武器的强大威力。本人根据自己多年在UNIX?-like系统上的琢磨和捣鼓,或许可以用最简洁、最切中要害的方法,向你们解明RegExp的基本精义。

※在当前的FreeBSD系统中,虽然/usr/bin/grep/usr/bin/egrep两个程序完全一致,但要用到egrep(扩充语法的grep),还是必须显式地使用egrep命令,或用“grep -E”。下面的内容,是针对egrep的(更简单、更强大)。

—— 只要八个汉字:

转义、数量、位置、逻辑




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论