会员登陆  支付方式  联系我们  在线客服  网站地图       
首页 关于域浪 互联网数据中心业务、主机托管、主机租用、机架租用、带宽租用、机房介绍、机房对比、CCN网络加速 adsl专线、深圳adsl专线 虚拟主机、域名注册、数据库、企业邮局、动态域名 网络安全、网络临近平台、安全服务、防火去墙租用、安全产品、域浪抗DDOS防火墙、NetScreen防火墙 技术支持  
   当前位置:首页 >> 技术支持 >> SHELL技巧 >> shell命令
 
精华文章
    AIX shell工具集  
    I/O重定向 详解及例子  
    Shell 编程实例集锦  
    Linux下Shell基础知识...  
    Linux下Shell基础知识...  
    Linux下Shell基础知识...  
    Linux下Shell基础知识...  
    Linux Shell 下的输出...  
    几个shell程序设计小知...  
    几种常见shell简介  
    shell基础十二篇  
    Shell编程基础  
    Bourne Shell及shell编...  
    shell命令(三)  
    shell命令(二)  
    shell命令(一)  
    shell基础:输入和输出...  
    shell命令  
    shell编程入门及脚本测...  
    Linux Shells简介  
    TCSH Shell编程  
    Korn Shell编程  
    Shell基础及编程(二)  
    Shell基础及编程(一)  
    shell基础知识  
    shell编程例子 -- 一个...  
    在LinuxShell程序中进...  
    SHELL病毒简介  
  更多>>  
   SHELL技巧
 shell命令
 系统打印提示符$,用户键入命令,命令得以执行,所有这些工作并不是直接由内核完成,而是由往返于内核和用户之间的命令解释程序或称shell的程序协调完成。 shell能够做一些特殊的工作,然而它也是一个普通程序,如同date或who一样。用shell连接用户和核心程序有不少优点,这里只讨论其中三个优点:



    i 文件名可以缩写:指定一定模式作为文件名的方法,可以将一组文件作为某一程序的参量。shell可以找出与给定模式相匹配的所有文件。



    i 输入输出可以重新定向:shell可以改变各种程序的标准输出;使它由输出到终端变成输出到某个文件;同样shell可以重新安排程序输入,使它由从终端输入变成从某个文件输入。



    i 建立个人喜爱的运行环境:shell允许用户定义自己的命令和缩写符号。



    7.4.1 文件名的缩写



    为说清楚这个问题,我们从文件名的模式匹配入手。如果你要键入一个很大的文件,如一部书那样,由于编辑一个很大的文件是相当累赘的,所以将一个大文件从物理存储上进行划分是很有必要的。例如先按章划分,称作ch1,ch2等等;然后每章又分成若干节,这样建立如下文件:



    ch1.1



    ch1.2



    ch1.3



    …



    ch2.1



    ch2.2



    …



    如果你需要打印整部书该怎样做呢?当然可以键入命令:



    $ pr ch1.1 ch1.2 ch1.3…



    对各个文件都要键入名字,不但令人感到厌烦,而且会出现错误。这就是需要文件名缩写的原因。如果使用命令:



    $ pr ch*



    shell把*号解释成一个符号串。这样ch*就是当前目录中以ch打头的所有文件。pr命令不能处理*,模式匹配工作由shell完成,它在当前目录里生成一张字符串表,并送到pr中。



    如前所述,文件名的缩写并不是由pr命令直接处理,而是shell提供了解释翻译服务。shell对其它命令也可以提供相似的服务, 例如对于wc程序:



    $ wc ch1.*



    113 562 3200 ch1.0



    935 4081 22435 ch1.1



    974 4191 22756 ch1.2



    378 1561 8481 ch1.3



    1293 5298 28841 ch1.4



    33 194 1190 ch1.5



    75 323 2030 ch1.6



    3801 16210 88933 total



    下面让我们看看echo程序对缩写符的响应。如同echo字面意义所表示的那样,echo只返送它的参数,此外再也不做别的事情。



    $ echo hello world



    hello world



    可以通过模式匹配生成echo的参数,这样



    $ echo ch1.*



    列出所有文件名中含ch1的文件;而



    $ echo*



    是按字母次序列出当前目录的所有文件名



    $ pr *



    打印当前目录中所有文件(按字母顺序)而



    $ rm *



    删除当前目录中的所有文件。(对这种命令要慎重!)



    *号不局限于文件名的最后位置,它可以处在任何位置,并可以重复出现多次。下面这个命令表示



    $ rm * .save



    删除所有以.save结尾的文件。



    注意文件名是以字母顺序存放的,与数字次序不同。若你的书有10章,所排的次序可能不是你想要的次序,ch10会排到ch2之前!



    $ echo *



    ch1.1 ch1.2 … ch10.1 ch10.2 … ch2.1 ch2.2 …



    *号不是shell提供的唯一匹配模式符号,尽管它使用得最多。模式[…]是与括号中的字符号进行匹配。首尾相连的一串字母或数字可以缩写成:



    $ pr ch [12346789] *



    打印第1,2,3,4,6,7,8,9章(没有第5章)



    $pr ch [1-46-9] * 同上



    $ rm temp [a-z] 删除文件tempa,… tempz.



    问号?匹配单个字符模式:



    $ ls ? 列出所有以单个字符命令的文件



    $ ls –l ch? .1



    列出文件ch1.1,ch2.1,ch3.1等等,但是没有ch10.1



    $ rm temp? 删除文件temp1,…tempa等等



    注意:模式仅对存在的文件名进行匹配,而不能产生新的文件名。举例来说,假如你想把每个文件的ch扩展成为chapter,不能采用下面的方法:



    $ mv ch.* chapter.*



    此命令不能工作因为与chapter.*匹配的文件不存在。



    象*号这类模式匹配的特殊符号同样可用于路径名和一般文件名。对于含有特殊字符的路径分量均可进行模式匹配。这样,/usr/frank/*与/usr/frank匹配,而/usr/*/calendar生成所有用户calendar文件的路径名表。



    如果你必须将专用符* 、?等等当作普通符,可以把它们括在单引号内,如



    $ ls ‘?’



    你也可以在特殊符前置予反斜杠,以达到同样目的。



    $ ls /?



    (记住因为?符不是删字符,删行符,所以反斜杠是由shell而不是由内核解释的)。



    7.4.2 输入输出重新定向



    至此为止,我们看到的大部分命令都在终端上进行输出;有些程序,如编辑程序,还可在终端上进行输入。一般来说,终端的输入输出都可以用一个文件代替它。例如:



    $ ls



    在终端上显示一个文件名表。如果你键入命令:



    $ ls >filelist



    原来输出到终端的文件名表将输出到文件filelist中。符号>的意义是“把输出送到其后的参数文件中,而不是送至终端”。如果指定的文件并不存在,则该文件被建立;如果文件已存在,则原来的内容将被覆盖掉;终端上将再看不到什么。另一个重新定向的例子是捕获cat文件的输出,把几个文件联结起来:



    $ cat f1 f2 f3 >temp



    符号>>的功能和>类似,其意义是把标准输出“附加到指定文件后面”,所以命令



    $ cat f1 f2 f3>>temp



    是把f1,f2,f3的内容复制到temp文件现有内容的尾部,而不是覆盖文件原来的内容。当temp这类文件参数不存在时,>符生成一个命名文件。



    类似地,符号<意味着程序从其后的参数文件输入,而不是从终端输入。这样,你可以将一个信件文件let,用下面命令将它发送给几个人:



    $ mail renee wang zhang <let



    在所有这些例子中,空格符可在符号>或<的任何一边。



    利用重新定向输出符>和其它命令相组合,可以实现一般命令不能完成的工作。下面是打印一份按字母次序排列的用户表:



    $ who >temp



    $ sort <temp



    因为who对每个注册用户有一行输出,而wh-1可以逐行进行计数(不做词和字符计数),因此可用如下二条命令计算注册用户数目:



    $ who >temp



    $ wc –1 <temp



    还可以用如下方法对当前目录里的文件进行计数:



    $ ls >temp



    $ wc –1 <temp



    其中文件temp也包括在内。下面是将文件名打印成三列形式:



    $ ls >temp



    $ pr –3 <temp



    通过who和grep命令的组合可以查询某个用户注册与否:



    $ who >temp



    $ grep wang <temp



    与文件名模式匹配符*一样,输入输出重新定向符>和<的解释由shell实现,而不是由这些命令实现。由shell实现的主要好处是,输入输出重新定向可以用于任何程序;而这些程序本身无需知道这是如何处理的。



    为了加深理解重新定向的概念,先考察命令:



    $ sort <temp



    这是对temp文件的内容进行排序。运行结果和下述命令的结果相同:



    $ sort temp



    但这里有一个要领上的不同:在第一个命令中,字符串<temp是由shell解释,sort排序程序不是以文件名temp作为它的参数,而是从标准输入读入文件,标准输入是由shell从文件重新定向中得到。在第二个命令中,文件名temp作为sort的参数,sort直接读文件并且对它排序。sort可以有若干个文件名作为参数,下面便是一个例子:



    $ xort temp1 temp2 temp3



    当没有给出文件名时,则对标准输入进行排序。这正是Linux系统大多数命令的基本特征:在没有指定文件名时,将从标准输入进行读取。为了证实这点,你可以键入一些命令,看看它们工作结果。例如:



    $ sort



    ghi



    abc



    def



    ctl-d



    abc



    def



    ghi



7.4.3 管道



    在前一节的所有例子中,信息的传送都采用如下的方法;这就是把一个程序的输出经过暂存文件转换成另一个程序的输入。暂存文件除了暂时存放的数据外没有别的功能。由于使用暂存文件并不是理想的办法,由此引出了Linux系统的一个重要特点,即使用了管道的思想。管道的作用是把一个程序的输出接到另一个程序的输入,而不经过任何中间文件;管道线是指连接二个或更多程序管道的通路。



    下面我们用管道代替暂存文件,重做前面的一些命令。在shell中字符|表示管道线。



    $ who | sort 打印用户排序表



    $ who | wc –1 计算用户数目



    $ ls | wc –1 计算文件数目



    $ ls | pr –3 以3列形式打印文件名表



    $ who | grep wang 查询用户wang是否上机



    要从终端读取的程序均可从管道读取;同样要写到终端的程序也可写到管道。这就是一般命令中作为参数的文件名不存在时,要求从标准输入读入的理由。任何遵循这一惯例的程序都可以用于管道线。grep,pr,sort和wc都可以在上述管道线上工作。



    根据用户的需要,管道线可以连接多个程序。例如命令



    $ ls | pr –3 | lpr



    表示在行式打印机上,输出一份3列的文件名表。而下面命令



    $ who | grep wang | wc –1



    计算用户wang注册登记了多少次。



    管道线上的程序实际上是同时运行的,而不是一个接一个地按先后顺序运行。这表明在管道线上的程序可以交互工作;为了使管道线上的程序全部一起运行,内核必须随时进行时间调度和同步协调。



    可能你现在对请示管道时shell做的事情还存在疑问,即管道中各个程序并不清楚重新定向问题,当然程序以组合方式工作时,它们的关系会更清楚些。大多数程序的开发都遵循一个共同的设计原则,这就是要使它们在管道线上的任何位置都可以正常工作。命令写格式通常如下:



    command optional-arguments optional-filenames



    命令 选择参数,选择文件名



    如果没有给出文件名,命令的输入来自标准输入,省缺值时输入来自终端,重新定向输入来自文件或管道。在输出方面,同样地多数命令将输出写到标准输出,标准输出省缺时送到终端,也可以重新定向输出到一个文件或管道。



    命令的错误信息应该单独作出处理。错误信息不应送入重新定向的文件或管道上,以防其丢失。所以每个命令设有标准错误输出,通常它指向用户终端.







图7-1 命令的处理



至此为止,我们遇到的命令几乎都符合这一命令模式,只有个别命令例外,如date和who命令,它们没有输入;cmp和diff命令要有固定的文件输入数目(不过需要注意这些命令的‘-’选择项)。



7.4.4 进程



    shell除了建立管道之外还有许多别的功能。下面我们讨论一次运行几条命令的情况,在管道使用中我们已遇到过。另外,在一个命令中用分号隔开两个命令,命令解释程序能够识别分号,并把命令行分成两个命令并给予执行,例如:



    $ date; who



    Thu Mar 25 10:53:41 GMT 1999



    frank         tty1         Mar 26 23:45



    renee         tty2         Mar 26 23:59



    wang          tty3         Mar 27 00:06



    qhua          tty4         Mar 26 23:31



    shell顺序执行两条命令,然后再送提示符到终端。



    如果需要的话,你可行同时运行一个以上的程序。例如,你想做一些相当耗费时间的事情,如对一本书的字数进行统计。但你不打算等待计数程序wc结束再开始做其它工作,那么可以键入命令:



    $ wc ch * >wc.out &



    6944                 命令shell打印出的进程标识号



    在命令行结束时的符号&将告诉shell“开始运行命令,然后询问终端的下一个命令”。因此,在命令开始执行后,便可以在命令运行过程中做其它工作。上例的程序将输出保留在文件wc.out中,保证其结果不受其他事情的干扰。



    程序运行称作进程。shell为响应&符而打印的数目称作进程标识号;它可用来干予指定程序的运行。



    程序和进程的区分是很重要的。wc是一个程序,每当你运行程序wc一次,便产生一个新进程。假如在同一时间几次运行同一程序,那么每次的进程有不同的进程标识号。



    例如,运行一个带&的管道线,如下所述



    $ pr ch * | lpr &



    6951                 lpr进程标识号



    由于符号&作用到整个管道线。因此所有进程都立即起动,然而终端上只打印一个进程号,这是一序列进程中的最后一个进程的标识号。



    命令



    $ wait



    一直等到&启动的所有进程结。假如没有发生什么响应,表明你的命令还在运行。你可以用DELETE来中止等待。



    根据进程标识号,使用kill命令便可终止某个进程:



    $ kill 6944



    若忘记了进程标识号,ps命令会告诉你正在运行程序的进程标识号。kill 0命令终止你所有的进程,而只留下注册登记的shell进程。如果你想了解其它用户在做什么,ps-ag将告诉你当前系统在运行的全部进程。下面是一个ps程序的输出:



    $ ps –ag



    PID     TTY     TIME     CMD



    36       co     6:29     /etc/cron



    6423     5      0:02     -sh



    6704     1      0:04     -sh



    6722     1      0:12     vi pager



    4430     2      0:03     -sh



    6612     7      0:03     -sh



    6628     7      1:13     rogue



    6843     2      0:02     write dmr



    6949     4      0:01     login bimmler



    6952     5      0:08     pr ch1.1 ch1.2 ch1.3 ch1.4



    6951     5      0:03     lpr



    6959     5      0:02     ps –ag



    6844     1      0:02     write rob



    PID是进程标识号;TTY是与该进程相关联终端号(表示谁的进程);TIME是进程花费时间(以秒计算);最后是运行的命令的名称。



    进程和文件系统有类似的层次结构:每一个进程有其父进程,还可以有其子进程。你的shell是由专门的进程生成的,这一进程主要管理系统与终端间的连结。运行命令的进程,是shell进程的直接子进程。如果你在这些进程里运行别的程序;例如在编辑程序ed的进程中使用!命令运行其它程序,ed就生成了一个自己的子进程,而这一子进程正是shell的孙进程。



    有时进程执行时间太长,以至等不到它结束就要关闭终端下班。终端一旦关闭或断开连线,所有进程都要终止,即使已使用了&符也是如此。命令nohup(“nohangup”)可以用于处理这一情况:当你键入



    $ nohup command &



    这一命令使程序在你退出注册后仍然继续运行。命令中的任何输出均放在nohup文件里。一般再没有停止nohup命令的办法。



    假如你的进程需要占用较多的处理机资源,而其它用户与你共享这些资源,在这样情况下,用低优先级运行下机后的程序是比较适宜的。这可以由另一个程序nice完成:



    $ nice expensive-command &



    nohup自动调用nice,由于你在退出注册再运行程序,稍长的运行时间是可以接受的。



    最后,还可以告诉系统在凌晨某个时间运行你的程序。因为凌晨很少有人使用机器,这时使用命令at(1):



    $ at time



    whatever commands



    you want …



    ctl-d



    这是一个典型的用法,当然命令参数也可以存放在文件中:



    $ at 3am <file



    时间可用24小时制,如2130;也可用12小时制,如930pm。



    7.4.5 环境裁剪



    Linux系统的优点之一是尽可能地适应个人使用习惯,尽可能地与勘察计算机的使用环境相兼容。例如,我们以前提到关于删字符,删行符的不同标准问题,它们的省缺值分别是#和@。用如下方法随时可把它们改变成你所要求的符号



    $ stty erase e kill k



    这时e是删字符,k是删行符。不过在每次注册登记时,要键入这些符号是很不方便的。



    shell提供了令人满意的解决方法。在你的注册目录里设置一个名为.profile的文件;每次注册登录时,shell在打印第一个提示符之前先执行这些命令。如果相应的命令放在.profile文件里,就建立一个你所喜欢的运行环境。这些命令在每次注册时,都自动运行一次。



    大多数用户在.profile文件里首先放入



    stty erase?



    这里我们使用符号?表示退格符,以便看到这个符号,也可以放一个文字符号的退格符在.profile文件里,stty将^x解释为ctl-x,因此用下列命令也达到同样效果:



    stty erase ‘^h’



    ctl-h便是退格符(^符号与管道操作符是同义词,所以必须用引号加以保护)。



    如果终端没有处理tab(表格符)停止位的功能,可在stty命令行里加上-tab选择项:



    stty erase ‘^h’ –tabs



    如果在注册登录时想查看系统里已有多少用户,可键入



    who | wc –1



    如果你觉得这样注册登录花费时间太多,可以适当剪裁.profile文件,使之只包含最必要的部分。



    shell的一些特性是由shell变量参数控制的。举例来说,我们经常显示的提示符$实际上是存储在shell变量psl里的字符串,你可以把它设置成任何字符串,如:



    PS1= ‘Yes dear?’



    上式中的引号是必需的,因为在提示符串中间有空格。在这一命令行里=号前后是不允许出现空格符的。



    shell还处理变量HOME和MAIL。HOME是户主目录,一般来说它不用.profile文件处理就可以正确设置。MAIL命令存放信件的标准文件,如果给shell定义一个MAIL,当你有邮件时,在每个命令之后便会接到新的信件到达的通知:



    MAIL= /usr/spool/mail/you



    (在你的系统里信件文件可能有所不同,通常使用/usr/mail/you)



    shell最有用的变量是查找命令路径控制的变量。在键入命令后,shell一般先查找当前目录,然后是/bin,最后/usr/bin。此种目录顺序称作搜索路径,并存储在shell变量PATH里。搜索路径是可以修改的,一般用.profile文件进行修改。例如,下面的设置是标准的路径加上/usr/games:



    PATH =.:/bin:/usr/bin:/usr/games



    这是路径设置的第一种方法。上式的语法有点特殊,是用冒号将目录名分隔开。记住‘.’是当前目录。也可以省掉‘.’不用,而用PATH里空白部分表示当前目录。



    另一个建立PATH的写法是直接用原来的路途作为参数:



    PATH= $PATH:/usr/games



    在名字前置以符号$表示shell原先参数值。在上例中,表达式$PATH表达PATH的当前值,再加上新的值,一起赋给PATH。可以用echo命令对其进行校验。



    $ echo PATH is $PATH



    PATH is :/bin:/usr/bin:/usr/games



    $ echo $HOME                                 你的注册目录



    /usr/you



    假如你有一些自己的命令,你可以把它们放在个人的目录里,并将其加到你的命令搜索路径中。此时,你的PATH可表示为:



    PATH= :$HOME/bin:/bin:/usr/bin:/usr/games



    另一个变量TERM用于设置终端特性。当使用高级屏幕编辑程序时,为了管理屏幕需要设置终端特性,可以将类似的行:



    TERM=adm3 打入.profile文件里。



    另外,可以用缩写变量代替长字符串。如果你经常访问很长的目录,可以将



    d=/horribly/long/directory/name 加到.profile文件中,然后键入命令:



    $ cd $d



    用户个人的变量,一般要求用小写字母拼写,如d等;而shell的变量常用大写,如PATH等。



    最后,还需要告诉shell你打算在其它程序里使用哪些变量,这可以通过export命令实现,其形式为:



    export MAIL PATH TERM



    下面是一个.profile文件的例子:



    $ cat .profile



    stty erase ‘^h’ –tabs



    MAIL=/usr/spool/mail/you



    PATH=:$HOME/bin:/bin:/usr/bin:/usr/games



    TERM=adm3



    b=$HOME/book



    expert MAIL PATH TERM b



    date



    who | wc –1



    以上介绍的只是shell的基本概况。Linux系统还有很多资源,其中一个很有用的资源是把一些现有的命令组合成一个文件,shell解释并执行这些文件,从而生成你自己的命令,这种实现各种复杂的功能是十分经济的。

  • 上一篇文章: shell基础:输入和输出(echo,read,cat,管道,tee,重定向等)
  • 下一篇文章: shell编程入门及脚本测试
  • 域浪网络ISP经营许可证 深圳地址:深圳市罗湖区宝安北路国际商品交易大厦七楼C30室
    Tel:0755-82266883/82267566 Fax:0755-82261966
    邮编:518000 
                        Copyright © 2006-2008 elang.cn All Rights Reserved 深圳市域浪网络技术有限公司版权所有