第1问:为何叫做shell?
在介绍 shell 是什么东西之前,不妨让我们重新审视使用者与电脑的关系。我们知道电脑的运作不能离开硬件,但使用者却无法直接对硬件作驱动,硬件的驱动只能透过一个称为“操作系统(Operating System)”的软件来控管,事实上,我们每天所谈的linux,严格来说只是一个操作系统,我们称之为“核心(kernel)”。然而,从使用者的角度来说,使用者也没办法直接操作kernel,而是透过kernel的“外壳”程序,也就是所谓的shell,来与kernel沟通。
这也正是kernel跟shell的形像命名关系。
从技术角度来说,shell是一个使用者与系统的互动界面(interface),主要是让使用者透过命令行(command line)来使用系统以完成工作。因此,shell的最简单的定义就是---命令解释器(Command Interpreter):
- 将使用者的命令翻译给核心处理,
- 同时,将核心处理结果翻译给使用者。
每次当我们完成系统登入(log in),我们就取得一个互动模式的shell,也称为login shell或primary shell。若从行程(process)角度来说,我们在shell所下达的命令,均是shell所产生的子行程。这现像,我们暂可称之为fork。如果是执行脚本(shell script)的话,脚本中的命令则是由另外一个非互动模式的子shell(sub shell)来执行的。也就是primary shell产生sub shell的行程,sub shell再产生script中所有命令的行程。(关于行程,我们日后有机会再补充。)
这里,我们必须知道:kernel与shell是不同的两套软件,而且都是可以被替换的:
- 不同的操作系统使用不同的kernel,
- 而在同一个kernel之上,也可使用不同的shell。
在linux的预设系统中,通常都可以找到好几种不同的shell,且通常会被列于如下档案里:
/etc/shells
不同的shell有着不同的功能,且也彼此各异、或说“大同小异”。常见的shell主要分为两大主流:
sh:
- burne shell(sh)
- burne again shell(bash)
csh:
- c shell(csh)
- tc shell(tcsh)
- korn shell(ksh)
大部份的Linux系统的预设shell都是bash,其原因大致如下两点:
- 自由软件
- 功能强大
bash是gnu project最成功的产品之一,自推出以来深受广大Unix用户喜爱,且也逐渐成为不少组织的系统标准。
第2问:shell prompt(PS1)与 Carriage Return(CR)的关系?
当你成功登录进一个文字界面之后,大部份情形下,你会在荧幕上看到一个不断闪烁的方块或底线(视不同版本而别),我们称之为游标(cursor)。游标的作用就是告诉你接下来你从键盘输入的按键所插入的位置,且每输入一键游标便向右边移动一个格子,若连续输入太多的话,则自动接在下一行输入。假如你刚完成登录还没输入任何按键之前,你所看到的游标所在位置的同一行的左边部份,我们称之为提示符号(prompt)。提示符号的格式或因不同系统版本而各有不同,在Linux上,只需留意最接近游标的一个可见的提示符号,通常是如下两者之一:
- $:给一般使用者帐号使用
- #:给root(管理员)帐号使用
事实上,shell prompt的意思很简单:是shell告诉使用者:您现在可以输入命令行了。我们可以说,使用者只有在得到shell prompt才能打命令行,而cursor是指示键盘在命令行所输入的位置,使用者每输入一个键,cursor就往后移动一格,直到碰到命令行读进CR(Carriage Return,由Enter键产生)字符为止。CR的意思也很简单:是使用者告诉shell:老兄你可以执行我的命令了。
严格来说:所谓的命令行,就是在shell prompt与CR字符之间所输入的文字。(思考:为何我们这里坚持使用CR字符而不说Enter键呢?答案在后面的学习中揭晓。)不同的命令可接受的命令行格式或有不同,一般情况下,一个标准的命令行格式为如下所列:
command-name options argument
若从技术细节来看,shell会依据IFS(Internal Field Seperator)将command line所输入的文字给拆解为“字段”(word)。然后再针对特殊字符(meta)先作处理,最后再重组整行command line。(注意:请务必理解上两句话的意思,我们日后的学习中会常回到这里思考。)
其中的IFS是shell预设使用的字段分隔符号,可以由一个及多个如下按键组成:
- 空白键(White Space)
- 表格键(Tab)
- 回车键(Enter)
系统可接受的命令名称(command-name)可以从如下途径获得:
明确路径所指定的外部命令
- 命令别名(alias)
- 自定功能(function)
- shell内置命令(built-in)
- $PATH之下的外部命令
每一个命令行均必需含用命令名称,这是不能缺少的。
第3问:别人echo、你也echo,是问echo知多少?
承接上一章所介绍的command line,这里我们用echo这个命令加以进一步说明。温习---标准的command line包含三个部件:
command_name option argument
echo是一个非常简单、直接的Linux命令:将argument送出至标准输出(STDOUT),通常就是在显示器(monitor)上输出。(注:stdout我们日后有机会再解说)。为了更好理解,不如先让我们先跑一下echo命令好了:
$ echo
你会发现只有一个空白行,然后又回到shell prompt上了。这是因为echo在预设上,在显示完argument之后,还会送出一个换行符号(new-line charactor)。但是上面的command并没任何的argument,那结果就只剩一个换行符号了…
若你要取消这个换行符号,可利用echo的-n option:
$ echo -n
不妨让我们回到command line的概念上来讨论上例的echo命令好了:command line只有command_name(echo)及option(-n),并没有任何argument。
要想看看echo的argument,那还不简单﹗接下来,你可试试如下的输入:
$ echo first line first line $ echo -n first line first line $</div>
于上两个echo命令中,你会发现argument的部份显示在你的荧幕,而换行符号则视-n option的有无而别。
很明显的,第二个echo由于换行符号被取消了,接下来的shell prompt就接在输出结果同一行了…^_^
事实上,echo除了-n options之外,常用选项还有:
- -e:启用反斜线控制字符的转换(参考下表)
- -E:关闭反斜线控制字符的转换(预设如此)
- -n:取消行末之换行符号(与-e选项下的\c字符同意)
关于echo命令所支持的反斜线控制字符如下表:
- \a:ALERT / BELL(从系统喇叭送出铃声)
- \b:BACKSPACE,也就是向左退格键
- \c:取消行末之换行符号
- \E:ESCAPE,跳脱键
- \f:FORMFEED,分页字符
- \n:NEWLINE,换行字符
- \r:RETURN,回车键
- \t:TAB,表格跳位键
- \v:VERTICAL TAB,垂直表格跳位键
- \n:ASCII八进位编码(以x开首为十六进位)
- \\:反斜线本身
(表格数据来自O'Reilly出版社之Learning the Bash Shell,2nd Ed.)
或许,我们可以透过实例来了解echo的选项及控制字符:
例一:
$ echo -e "a\tb\tc\nd\te\tf" a b c d e f</div>
上例运用\t来区隔abc还有def,及用\n将def换至下一行。
例二:
$ echo -e "\141\011\142\011\143\012\144\011\145\011\146" a b c d e f</div>
与例一的结果一样,只是使用ASCII八进位编码。
例三:
$ echo -e "\x61\x09\x62\x09\x63\x0a\x64\x09\x65\x09\x66" a b c d e f</div>
与例二差不多,只是这次换用ASCII十六进位编码。
例四:
$ echo -ne "a\tb\tc\nd\te\bf\a" a b c d f $</div>
因为e字母后面是退格键(\b),因此输出结果就没有e了。在结束时听到一声铃向,那是\a的杰作﹗
由于同时使用了-n选项,因此shell prompt紧接在第二行之后。若你不用-n的话,那你在\a后再加个\c,也是同样的效果。
事实上,在日后的shell操作及shell script设计上,echo命令是最常被使用的命令之一。
比方说,用echo来检查变量值:
$ A=B $ echo $A B $ echo $? 0</div>
(注:关于变量概念,我们留到下两章才跟大家说明。)
好了,更多的关于command line的格式,以及echo命令的选项,就请您自行多加练习、运用了…
第4问:“”(双引号)与''(单引号)差在哪?
还是回到我们的command line来吧…
经过前面两章的学习,应该很清楚当你在shell prompt后面敲打键盘、直到按下Enter的时候,
你输入的文字就是command line了,然后shell才会以行程的方式执行你所交给它的命令。但是,你又可知道:你在command line输入的每一个文字,对shell来说,是有类别之分的呢?
简单而言(我不敢说这是精确的定议,注一),

