认识BASH Shell(1)

发表于:2007-07-04来源:作者:点击数: 标签:
什么是 Shell 这应该是个蛮有趣的话题:『什么是 Shell ?』相信只要摸过 电脑 ,对于作业系统(不论是 Linux 、 Unix 或者是 Windows )有点概念的朋友们大多听过这个名词,因为只要有『作业系统』那么就离不开 Shell 这个东西。不过,在讨论 Shell 之前,
什么是 Shell

这应该是个蛮有趣的话题:『什么是 Shell ?』相信只要摸过电脑,对于作业系统(不论是 Linux 、 Unix 或者是 Windows )有点概念的朋友们大多听过这个名词,因为只要有『作业系统』那么就离不开 Shell 这个东西。不过,在讨论 Shell 之前,我们先来了解一下电脑的运作状况吧!举个例子来说:当你要电脑传输出来『音乐』的时候,你的电脑需要什么东西呢?

1. 当然就是需要你的硬体有『音效卡晶片』这个硬体配备,否则怎么会有声音;

2. 作业系统的核心可以支援这个晶片组,当然还需要提供晶片的驱动程式啰;

3. 需要使用者(就是你)输入发生声音的指令啰!

这就是基本的一个输出声音的需要的步骤!那么也就是说,你必须要『输入』一个指令之后,『硬体』才会透过你下达的指令来工作!嘿嘿!那么硬体如何知道你下达的指令呢?那就是 kernel (核心)的控制工作了!了解了吗?没错!也就是说,我们必须要透过『 Shell 』将我们输入的指令与 Kernel 沟通,好让 Kernel 可以控制硬体来正确无误的工作!基本上,我们可以透过底下这两张图来说明一下:

 javascript:window.open(this.src);" style="CURSOR: pointer" onload="return imgzoom(this,550)">

基本上,替我们工作的是『硬体』,而控制硬体的是『核心』,再来,我们使用者乃是利用『Shell』控制一些 kernel 提供的 『工具 Utility』来操控硬体替我们正确的工作。再举个例子来说,当我们使用 shell 的功能,输入『 cd /』来切换目录时, shell 便利用 kernel 提供的 cd 工具来告诉 kernel 转换硬碟的工作目录到 / 当中,然后硬碟就根据 kernel 的掌控而切换到 / 当中啰!这个就是 Shell 的主要功能啰!再进一步来说,由于 kernel 听不懂人类的语言,而人类也没有办法直接记得 kernel 的语言,所以两者的沟通就得藉由 shell 来支援了!

以字面上的意思来说, kernel 是『核心』的意思,而 Shell 是『壳』的意思,呵呵!也就是说, shell 是最外头的咚咚!而 kernel 乃是最内层的的咚咚啦!核心是作业系统的最底层的东西!这个核心里头包括了各种的支援硬体的工具!当然啰,如果你的硬体太新,而你的 kernel 并没有支援的话,那么很抱歉,你的 Shell 能力再怎么强,也没有办法使硬体工作的!这样可以了解了吗?呵呵!没错!使电脑主机工作的正是核心的任务,但是操作核心来替使用者工作的,却是 shell 喔!因此,有时候你的 shell 搞了老半天,硬体却不能工作的时候,请注意,您的『核心』是否正确呢?阿!扯远了!这是 kernel 章节才要说的东西~~

BASH Shell

知道什么是 Shell 之后,那么我们来了解一下 Linux 使用的是哪一个 shell 呢?什么!哪一个?难道说 shell 不就是『一个 shell 吗?』哈哈!那可不!由于早年的 Unix 年代,发展者众,呵呵!所以由于 shell 依据发展者的不同就有许多的版本,例如常听到的 Bourne SHell (sh) 、在 Sun 里头预设的 C SHell、 商业上常用的 K SHell、, 还有 TCSH 等等,每一种 Shell 都各有其特点。至于 Linux 使用的这一种版本就称为『 Bourne Again SHell (简称 bash ) 』,这个 Shell 是 Bourne Shell 的增强版本,也是基准于 GNU 的架构下发展出来的呦!

在介绍 shell 的优点之前,先来说一说 shell 的简单历史吧:第一个流行的 shell 是由 Steven Bourne 发展出来的,为了纪念他所以就称为 Bourne shell ,或直接简称为 sh !而后来另一个广为流传的 shell 是由柏克莱大学的 Bill Joy 设计依附于 BSD 版的 Unix 系统中的 shell ,这个 shell 的语法有点类似 C 语言,所以才得名为 C shell ,简称为 csh !由于在学术界 Sun 主机势力相当的庞大,而 Sun 主要是 BSD 的分支之一,所以 C shell 也是另一个很重要而且流传很广的 shell 之一(因为太多的程式设计师使用的就是 C 语言啦!)!

好了,那么 BASH 是怎么一回事呢?这个 shell 是 GNU 计画中重要的工具软体之一,目前也是 GNU 作业系统中标准的 shell ,他主要相容于 sh 。所以,可想而知的,目前几乎所有的 Linux distribution 都是使用 bash 作为管理核心的主要 shell 啰!那么这个 shell 有什么好处,干嘛 Linux 要使用他作为预设的 shell 呢? BASH 主要的优点有底下几个:

· 命令编修能力(类似 DOS 的 doskey 功能):使用 bash 里头,个人认为相当棒的一个功能就是『他能记忆使用过的指令!』这功能真的相当的棒!因为我只要在指令列按『上下键』就可以找到前一个输入的指令!而预设的指令记忆功能可以到达 1000 个!也就是说,你曾经下达过的指令都被记录下来了,记录的档案在你的家目录内的 .bash_history !至于这一次登入所执行的指令都被暂存在暂存区中,成功的登出系统后,该指令记忆才会记录到 .bash_history 当中!这有什么功能呢?最大的好处就是可以『查询曾经做过的举动!』,如此可以知道你的执行步骤,那么就可以追踪您曾下达的指令,以作为除错的工具!但如此一来也有个烦恼,就是如果被骇客入侵了,那么他只要翻你曾经执行过的指令,刚好你的指令又跟系统有关(例如直接输入 MySQL 的密码在指令列上面)那么很容易就被破解你的 Linux 主机!所以,最好是将记录的指令数目减小一点较好!

·档案比对补全功能(比对资料正确性):这个功能也相当的棒!如果在执行命令的时候不想按下太多的按键,例如指令 pcprofiledump 够长吧!好了,那么如果你输入了 pcprofile 之后,再按下 [Tab] 按键的话,那么 bash 马上会自动的将后面的 dump 接上来!那如果有重复的指令呢?那么按下两次 [Tab] 将会把所有重复的指令给他列出来啰!

o直接在指令列按下 [Tab][Tab] 两次,那么 Linux 将会把系统内的所有执行档列出来;

另外一个优点就是,可以将该指令所进行的 parameter (与路径或档案相关的)比对后,列出正确的项目!举个例子来说,如果我要列出 /etc/sysconfig/network-scripts 里面的所有档案时,要如何下达参数?

o ls -al /etc/sysconfig/network-scripts

那我可以在输入到 network 时按下 [Tab] 按键,则 -scripts 就会被自动的加入命令列了!反正真的是蛮方便的,有事没事多按[tab] 按键是不错的一件事呦!

·命令别名(alias)设定功能:假如我需要知道这个目录底下的所有档案(包含隐藏档)及所有的档案属性,那么我就必须要下达 ls -al 这样的指令列,唉!真麻烦,有没有更快的取代方式?呵呵!就使用命令别名呀!例如我最喜欢直接以 lm 来取代上面的命令,也就是说, lm 会等于 ls -al 这样的一个功能,嘿!那么要如何作呢?就使用 alias 即可!你可以在指令列出入 alias 就可以知道目前的命令别名有哪些了!也可以直接下达命令来设定别名呦:

oalias lm='ls -al'

·工作控制 (jobs)、前景背景控制:这部分我们在之后的 指令篇会再提及!使用前、背景的控制可以让工作进行的更为顺利!至于工作控制(jobs)的用途则更广,可以让我们随时将工作丢到背景中执行!而不怕不小心使用了 [Ctrl] + C 来停掉该程序!真是好样的!

·Shell scripts 的强大功能:在 DOS 年代还记得将一堆指令写在一起的所谓的『批次档』吧?在 Linux 底下的 shell scripts 则发挥的更为强大的功能,可以将您日常生活当中常需要下达的连续指令写成一个档案,该档案并且可以透过对谈互动式的方式来进行主机的侦测工作!也可以藉由 shell 提供的环境变数及相关指令来进行设计,哇!整个设计下来几乎就是一个小型的程式语言了!该 scripts 的功能真的是超乎我的想象之外!以前在 DOS 底下需要程式语言才能写的东西,在 Linux 底下使用简单的 shell scripts 就可以帮你达成了!真的利害!!这部分我们在底下再来谈!

在了解了 BASH 的优点之后,再来我们要来讨论的是:那如何在 Shell 提供的环境中下达指令呢?其实很简单的,下达指令的方式为:

 

很简单吧!OK!那么再来一个问题:『Shell 是什么时候开始接管 Linux 主机的!?』如果您对于鸟哥前面提到的『开机流程』有稍微去了解一下的话,那么应该可以了解到 Linux 经由 Kernel 执行完毕,并且执行了 init 与 run-level 设定的一些 scripts 之后,接下来执行了 login 的程式,就可以顺利的进入到 shell 接管的程序了!当然啰,要等到使用者顺利的登入 Linux 之后,才可以使用 shell 来进行与主机沟通的动作呦!另外,需要注意的是,登入主机之后通常使用者的起始目录会在『家目录』, root 的家目录预设在 /root 底下,一般使用者的家目录则与 /etc/passwd 的设定有关!

变数与变数的设定:echo, env, set, 变数设定规则, export, unset,

再继续研究 BASH 之前,我们要就变数这个东西来讨论一番,因为在主机里面有太多的资料需要进行存取了,而这些资料都是一些服务所必须的,例如 mail 的存取路径在 /var/spool/mail 、家目录预设在 /home/useraclearcase/" target="_blank" >ccount 等等,当然我们可以改变这些个变数,但是如果该变数是直接深植于套件当中,那么当你修改了某些参数之后,嘿嘿!你的套件就必须要『由原始码直接更新再编译』才行!这样似乎很麻烦,所以啰,就会有变数这个好东西出来了!

 

举个简单的例子来说, sendmail 的 smtp 存放 mail 路径是经由 /etc/profile 里头的 MAIL="/var/spool/mail/$USER"来设定的,而当我修改了上面这一个咚咚,然后重新开机之后,嘿嘿嘿嘿!我的邮件就可以存放到不同的路径去了!而且不会有问题!可以顺利的『在 Linux 主机上面』收发。然而问题发生在 pop3 这个服务上面,由于 pop3 的预设路径是在 source code 里头,而且就正是 /var/spool/mail 这个路径,也就是说,不论我怎么修正我的『变数』, pop3 都不为所动!唉~真惨,所以就无法直接以 pop3 来收信了(例如 OutLook 就不能工作了)!会发生密码不接受的问题呢!

此外,例如我们在执行程式的时候,系统怎么知道你的 ls 这个指令放在哪里?原来是有 PATH 这个变数,系统会透过这个变数里面所设定的路径去依序寻找该指令系统,如果找不到的话,那么才在萤幕上显示『 command not found 』字样!这些还都只是系统预设的变数的目的,如果是个人的设定方面:例如你要写一个大型的 script (批次档)时,有些资料因为可能由于使用者习惯的不同而有差异(例如路径!),而由于该内容使用在 script 的地方相当的多,如果每次都需要修改该地方,则一定会疯掉!这个时候使用变数,而将该变数的定义写在最前面,嘿嘿!那么你只要修改一行就等于修改整篇 script 了!方便的很!所以,良好的程式设计师都会善用变数的定义!(这个部分我们在底下还会再提到!)

如果说的学理一点,那么由于在 Linux System 下面,所有的执行续都是需要一个执行码,而就如同上面提到的,你『真正以 shell 来跟 Linux 沟通,是在正确的登入 Linux 之后!』这个时候你就有一个 bash 的执行程序,也才可以真正的经由 bash 来跟系统沟通啰!而在进入 shell 之前,也正如同上面提到的,由于系统需要一些变数来提供他资料的存取(或者是一些环境的设定参数值,例如是否要显示彩色等等的),所以就有一些所谓的『环境变数』需要来读入系统中了!

说了那么久,那么到底『什么是变数』呢?简单的说,『变数就是以一组文字或符号等,来取代一些设定或者是一串保留的资料!』,例如:『VBird』就是『鸟哥』,所以当你读取 VBird 的时候,系统自然就会知道!哈!那就是鸟哥!最简单的例子可以取 PATH 来说明!如果你对于『相对路径与绝对路径』还有点印象的话,那么应该晓得『要下达正确的指令,应该需要指定路径与档名』才行!例如你的 ls 指令应该需要以『/bin/ls』来下达指令才对,那么为何你在任意的路径下都可以执行 ls 呢?而不需要指定路径呢?这是因为系统已经预设了一些『搜寻路径(PATH)』了,所以当你需要执行一些指令的时候,系统就会依照该 PATH 的设定来进行指令的搜寻!而这个 PATH 就是所谓的变数了!那么如何『显示变数』呢?这就需要使用到 echo 这个指令啦!

·echo

显示变数内容

语法:

 

就如同上面的范例,当我们要显示目前的 PATH 这个变数时,使用了 echo ,而为了要分辨是否为变数,那么 Linux 系统预设变数名称前面会加上一个『 $ 』符号,所以就必须要写成 echo $PATH 啰!

·有多少的环境变数呀?使用 env 与 set 来看看:

这是我们比较有兴趣的,那就是有多少的环境变数在 Linux 系统中呢?呵呵!你可以简单的使用 env 就可以知道啰!『基本上,在 Linux 预设的情况中,使用{大写的字母}来设定的变数一般为系统内定需要的变数』,底下列出 Red Hat 7.2 预设的变数内容:

·env

显示目前系统中主要的预设变数内容

语法:

 

 

env 这个指令主要在将目前系统中的主要变数读出来!但是我加上了 sort 就可以将资料进行排序啰!所以像上面的 PATH, USER, HOME 等等的资料就会被读出来啰!除了 env 这个指令之外,还有一个可以将目前系统中所有的变数资料都读出来的指令,称为 set !set 除了会将上面的资料都给他读出来之外,还会有额外的这些资讯也一起读入(通常都与使用者的设定有关!):

·set

显示目前系统中全部的变数内容

语法:

 

使用 set 除了会将系统的预设值秀出来之外,连带的所有的你自己设定的变数也会被秀出来!同时需要注意的是,若当时有相当多人同时在线上的话,那么你的变数只能给自己使用(除非改的是系统的预设参数档,如 /etc/profile ),而不会干扰到别人的!就如同前面所说的,由于你登入 Linux 之后会取得一个 PID ,而你的设定将只对这个 PID 与子程序有关!此外,这次登入所进行的变数设定,如果没有更动到设定档,那么这次设定的变数在下次登入时将被取消掉(因为程序 PID 不见啰!)!所以啰,如果你想要你的变数每次都能在你登入的时候自动就设定好了,那么就必须将你的设定写入登入时载入的设定档!

· 变数设定规则:

好了,我们知道了一些系统的预设变数了,但是如果是我自己想要设定一些我自己的变数,该如何设定呢?有什么规则需要遵守?呵呵!在说明之前,可能要来让大家了解一下为什么自己会想来设定变数?

我的案例一:最简单的例子就是『路径名称』啰!以鸟哥为例,我的工作在 Unix 系统之下进行一些数值模式的模拟工作,偏偏由于资料量太大,为了怕日后忘记这个目录的内容与主要的意义,所以我的档名都取的很长,偏偏在执行模式的过程中,常常会切换目录!我哩ㄌㄟ,光是打那几行路径名称就快要疯掉了!所以我就设定那几行目录名称成为一个四个字元的变数,如此一来我只要输入『 cd $VARI 』这个指令,嘿嘿!马上就移动到该路径下了!很方便吧!当然变数的意义还不止于此,不过这是最简单的实例说明啰!
我的案例二:另外一个常常需要变数的咚咚是在 scripts 里面,例如我写的一个侦测登录档的小程式 logfile.sh 这个咚咚,由于里头常常需要用到『储存路径』,偏偏可能每个人的存取路径都不太一样,而如果要修改存取路径的话,嘿嘿!好几十行要同时修改呢!还可能会改错!那么我只要定义一个变数,然后后续的所有资料都使用这个变数的内容!嘿嘿!那么只要大家修改了这个变数的内容(只要一行),后续的动作就不需要修正了!这个动作常在程式或者是 script 当中看到的!

所以啰,有很多的时候为了方便或者是使用于 scripts 的意义,我们必须要设定变数!然而在 bash 底下的变数设定是有一定规则的,必须要来遵守才行:

1. 变数与变数内容以等号来连结;

2. 等号两边不能直接接空白字元;

3. 变数名称只能是英文字母与数字,但是数字不能是开头字元;

4. 若有空白字元可以使用双引号『 " 』或单引号『 ' 』来将变数内容结合起来,但须要特别留意,双引号内可以保有变数,但是单引号则仅为一般字元;

5. 必要时需要以跳脱字元『 \ 』来将特殊符号(如 Enter, $, \, 空白字元, ' 等)变成一般符号;

6. 若该变数为扩增变数内容时,则需以双引号及 $变数名称如:『 "$PATH":/home』继续累加内容;

7. 若该变数需要在其他子程序执行,则需要以 export 来使变数可以动作,如『export PATH』;

8. 通常大写字元为系统预设变数,自行设定变数可以使用小写字元,方便判断(纯粹依照使用者兴趣与嗜好);

9. 取消变数的方法为:『unset 变数名称』。

底下我们举几个例子来说明一下:

 

 

根据上面的案例你可以试试看!就可以了解变数的设定啰!这个是很重要的呦!请勤加练习!!

bash shell 的设定档案: alias(设定命令别名), history, !command, source,

终于来到 bash 的设定档案啰!这部份我们预计分成『系统设定值』与『一般各人喜好设定值』来说明,除非您是 root ,并且对于大家的喜好有共同的认知,否则只要设定您的『个人设定值』(在每个人的家目录内)也就可以啰!

· 系统设定值:

所谓的系统设定值,也就是说每个使用者进入到 bash shell 之后,会先读取的设定档案!预设的设定档案有下列几个:

o /etc/profile:这个档案设定了几个重要的变数,例如:『PATH、USER、MAIL、HOSTNAME、HISTSIZE』等等,也同时规划出 inputrc 这个档案的资料内容,你可以在这里设定总体的 PATH 等等的资讯!同时,这个 file 也规划出 /etc/profile.d 及 /etc/inputrc 这两个档案,其中, inputrc 是用在 history (历史指令)的作用上的!总之,你可以了解到刚刚我们学会的变数设定方式,在这个档案中也可以设定呢!但是设定上需要特别小心,因为所有的使用者皆会使用到这个档案的资讯。注:通常我都喜欢将 /usr/local/bin 这个路径加成最前面,这是因为通常自己安装的套件自己最喜欢,所以当然是最先收寻啰! ^_^!此外,请注意一下,可以将 HISTSIZE 的大小改变一下,改成 50 就可以啦!比较安全

o /etc/bashrc:这个档案在规划 umask 的功能,也同时规划出提示字元的内容(就是里头那个 PS1 啦!)。

o /etc/man.config:这个档案或许跟 bash shell 较没相关性,但是对于系统管理员来说,却也是很重要的一个档案!这的档案的内容『规范了使用 man 的时候, man page 的路径到哪里去寻找!』所以说的简单一点,这个档案规定了下达 man 的时候,该去哪里查看资料的路径设定!那么什么时候要来修改这个档案呢?如果你是以 tarball 的方式来安装你的资料,那么你的 man page(指令说明档案)可能会放置在 /usr/local/softpackage/man 里头,那个 softpackage 是你的套件名称,这个时候你就得以手动的方式将该路径加到 /etc/man.config 里头,否则使用 man 的时候就会找不到相关的说明档啰!

这就是系统在设定的时候常常会使用的档案!需要特别留意的是,通常设定完了这几个档案之后,都需要先 logout 在 login 之后才会将设定整个启动起来!

· 个人设定值

那么个人的喜好设定在哪里?嘿嘿嘿嘿!那就是在个人家目录的几个隐藏档当中啰!分别会使用到底下的几个档案啦!(注意!都是隐藏档,需要使用 ls -al 方能显示出来),另外,注意一下啰!底下那个『 ~ 』代表的是『家目录』的意思!

o ~/.bash_profile:里面定义了个人化的路径(PATH)与环境变数的档案名称!你可以在这里修改你的个人路径呦!当然啰!也可以在 ~/.bashrc 这个个人设定的变数里头修改!

o ~/.bashrc:这个档案对于个人喜好的 bash 设定来说,是最重要的啦!因为我都是在这里设定我的个人化变数!例如命令别名的设定!路径的重新定义等等,都是在这里完成的!底下我们再仔细的讨论一下如何设定命令别名吧!

o ~/.bash_history:这个档案的用途在于将你曾经使用过的命令记录下来,而当你再次的以上下键搜寻或者直接以 history 搜寻的时候,就可以找到曾经使用过的指令啰!需要注意的是:

1. 在这一次的执行过程中的指令,将在你离开 shell 之后才会被纪录到这个档案中,否则将只会先被写到暂存记忆体中(Cache);

2. 可以藉由 history 这个指令来将里头的纪录搜寻出来;

3. 这个档案的指令记录笔数,与 HISTFILE 有关,你可以自行在 ~/.bashrc 里头设定,或者直接由 root 在 /etc/profile 里面统一设定大小!

o ~/.bash_logout:这个档案则是在『你登出 shell 的时候, BASH 会为你所做的事情!』通常预设是只有 clear 这件事情而已,不过,你也可以将一些备份或者是其他你认为重要的工作写在这个档案中(例如清空暂存档),那么当你离开 Linux 的时候,就可以解决一些烦人的事情啰!

大致上的个人设定就是如同上面说的!不过,我个人觉得比较重要的是 ~/.bashrc 这一个档案!我喜欢将自己的相关设定写在里头!这样可以很轻易的将个人的设定写好!尤其是命令别名与变数的设定等等!底下我们先来谈一谈『命令别名』与『历史指令记录』这两个东西,然后再来谈 ~/.bashrc 这个档案的一般各人喜好设定!

·命令别名:

命令别名是一个很有趣的东西,特别是你的惯用指令特别长的时候!还有,预防一些不小心误杀档案的情况发生的时候!举个例子来说,如果你要查询隐藏档,并且需要长的列出与一页一页翻看,那么需要下达『 ls -al | more 』这个指令,我是觉得很烦啦!要输入好几个单字!那可不可以使用 lm 来简化呢?!当然可以,你可以在命令列下面下达:

[test @tset test]# alias lm='ls -al | more'

要注意的是:『alias 的定义规则与变数定义规则几乎相同』,所以你只要在 alias 后面加上你的{『别名』='指令 参数' },以后你只要输入 lm 就相当于输入了 ls -al|more 这一串指令!很方便吧!另外,我们知道 root 可以移除( rm )任何资料!所以当你以 root 的身份在进行工作时,需要特别小心,但是总有失手的时候,那么 rm 提供了一个参数来让我们确认是否要移除该档案,那就是 -i 这个参数!所以,你可以这样做:

[test @tset test]# alias rm='rm -i'

嘿嘿!那么以后使用 rm 的时候,就不用太担心会有错误删除的情况了!这也是命令别名的优点啰!那么如何知道目前有哪些的命令别名呢?就使用 alias 呀!

[test @tset test]# alias

alias l.='ls -d .[a-zA-Z]* --color=tty'

alias ll='ls -l'

alias lm='ls -al'

alias ls='ls --color=tty'

alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

· 至于如果要取消命令别名的话,那么就使用 unalias 吧!

· 历史指令记录资料:

前面我们提过 bash 有提供指令历史的服务!那么如何查询我们曾经下达过的指令呢?就使用 history 啰!

o history, !command

显示历史指令记录内容, 下达历史纪录中的指令

语法:

 

说明:

基本上 history 的用途很大的!但是需要小心安全的问题!尤其是 root 的历史纪录档案,这是 Cracker 的最爱!因为不小心的 root 会将很多的重要资料在执行的过程中会被纪录在 ~/.bash_history 当中,如果这个档案被解析的话.....而使用『 ! 』配合曾经使用过的指令下达是很有效率的一个指令方法!

鸟哥的常用的个人喜好设定值:

底下是 VBird 最喜欢的设定值啰!大家可以随意的参考看看就好了!

[test @test test]# vi .bashrc

# .bashrc

# User specific aliases and functions

PATH="/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/sbin:/usr/bin:$PATH" <==常用!

export PATH

alias rm='rm -i'

alias cp='cp -i'

alias mv='mv -i'

alias ll='ls -l'

alias lm='ls -al|more' <==常用!

alias h='history'<==常用!

# Source global definitions

if [ -f /etc/bashrc ]; then

. /etc/bashrc

fi

[test @test test]# source ~/.bashrc<==將剛剛改的資料直接讀入這一次的程序當中!不需登出!

· 当然还有一些个人比较常用的变数,这里就不列出来了!那么改写完毕之后。此外,通常我们改写的这些设定,必须要登出再登入才能被启用!但是我们可以使用 source 来直接的启用他!这也是很多朋友为了因应不同的软体或者是其他的执行环境,而写了不同的环境设定档案(不一定是 .bashrc 这个档案),然后在需要的时候再以 source 来将设定读出来即可!这个指令可也是相当重要的呦!

万用字元与特殊符号

由于在 bash 当中常会使用到一些万用字元,与搭配特殊符号来将指令做更好的利用(例如最常提到的正规表示法 Regulare Express )!底下我们列出一些常用的万用字元与特殊符号!

 

上面的万用字元当中,最常用的就属 *, ?, [] 及 ` 了!我们提几个简单的例子:

[test @test test]# ls test* <==那個 * 代表後面不論接幾個字元都予以接受(沒有字元也接受!)

[test @test test]# ls test? <==那個 ? 代表後面『一定』要接『一個』字元

[test @test test]# ls test??? <==那個 ??? 代表『一定要接三個』字元!

[test @test test]# cp test[1-5] /tmp <==將 test1, test2, test3, test4, test5 若存在的話,就拷貝到 /tmp 下

[test @test test]# cd /lib/modules/`uname -r`/kernel/drivers <==被 ` ` 括起來的內容『會先執行』!

上面几个例子相当的有趣!尤其是最后面两个!需要注意的是, [] 里面『代表只有一个字元』但是范围可以由 1-5 ,这样来说的话,那么我们如果允许『大写字元』就可以将档案 copy 出来的话,可以这样做:

cp *[A-Z]* /tmp

很有趣吧?! ^_^

此外,那个 `` 里面的『指令』会先被执行,也就是说:

1. 系统先执行 uname -r 找出输出的结果;

2. 将结果累加在目录上面,来执行 cd 的功能!

很棒吧!!这些基本的功能需要特别来了解一下才行呦!

绝对路径与相对路径

其实,在使用 bash 还有另一个困扰,就是当你的 PATH 没有设定完整的时候,下达指令都是要以『一长列的指令连带根目录都要列出来』,呵呵那就是绝对路径的设定法啦!基本上,这个『绝对路径』与『相对路径』的观念是很重要的!否则你将常常会找不到档案说!所谓的『绝对路径』就是以根目录开始写入到档案的一种命令写定方法,举例来说,我目前在 /home/test 这个 test 使用者的家目录中,我想要看看里面的 .bashrc 这个档案的资料,使用的是 more 这个指令,而这个指令在 /bin/more 当中,则正确的下达指令的方法为:

[test @tset test]# /bin/more .bashrc <==我在的目录为 /home/test !这是绝对路径写法!

而如果你还记得我们在 档案系统指令 那一篇文章中提到的观念的话,那么应该记得使用 ls -al 时会出现两个一定存在的目录,分别是『.』与『..』,分别代表是『这个路径』,与『上一层路径』!

[test @tset test]# ls -al

total 728

drwx------3 vbirdvbird4096 May 19 14:53 . <==這一層路徑的屬性說明

drwxr-xr-x3 root root 4096 May 5 16:50 .. <==上一層路徑的屬性說明

以下略!

所以说,要执行上一层目录中的命令,可以下达『 cd ../command 』那个 command 指的是存在的可执行档!那么我因为在 /home/test 里面,距离 /bin 有两层上层目录,所以我要使用 /bin/more 这个执行档,并且使用相对路径的方法,就必须使用:

[test @tset test]# ../../bin/more .bashrc<==一层一层回到根目录,在进入 /bin 的写法!相对路径

这种相对路径的方法相当广泛的被运用于 script 当中,这是因为如前面提到的,每个人的安装预设的目录都不相同,则使用相对路径的话,很容易就可以找到套件之间相依软体或者是设定档案的相关性!

 

关于路径搜寻的问题!为何不执行目前所在目录下的档案?咦!刚刚不是提到『.』与『..』吗?那么那个『 . 』是干嘛用的?!眼尖的朋友应该已经发现了,就是『我在执行档案的时候,基本上,并不会主动搜寻目前目录下的档案』举个例子来说,我安装的 squid 这个执行档在 /usr/local/squid/bin/squid 这个档案,然而我在 /usr/local/squid/bin 下达 squid 的时候,系统会告诉你『查不到这个档案!』真是见鬼了!明明有这个档案的呀!这是因为系统预设的 PATH (路径)并没有执行目前目录下的设定,也就是『.』这个路径!你可以使用『 echo $PATH 』看看,就可以知道为什么了!那么为何不要设定这个路径呢?这是因为『安全』的考量。由于系统预设是允许任何人在 /tmp 底下写入任何档案的,那么万一有居心不良的使用者或者是 Cracker 入侵你的电脑,并在你的 /tmp 里头埋了一个小木马,并取名为 ls ,好了,改天你以 root 身份登入后,到 /tmp 底下,并执行 ls ,你看会有什么结果?!这个 /tmp/ls 由其他身份的人来执行或许没有问题,但是由 root 来执行却可能会导致 Cracker 所乐意见到的结果!那晓得为何了吧?!当然啰!您还是可以选择在 ~/.bashrc 当中设定你的 . 在你的 PATH 当中,不过并不这么建议就是了!

好了,由于系统预设并不主动搜寻目前目录下的执行档,那么你应该如何执行『目前目录下的执行档』呢?很简单呀!就是以相对路径的观念,由于『 .. 』是上层,而『 . 』是这一层,所以要执行这一层目录的命令就使用『 ./command 』即可!例如你的 /usr/local/squid/bin 底下执行 squid 则可以写成:

[test @tset bin]# ./squid  <==以相对路径的观念来看!在本目录下达的指令写法!

请特别留意这方面的问题!『新手特别容易犯这个错误呢!』
命令重导向

基本上,这个子题是 bash 相当重要的观念,这里可得花点心思才行呦!

o 什么是『重导向, redirect ?』:简单的说,就是将你目前的所得资料转到其他地方去就是了!例如我们常用的,将目前的萤幕输出资料转到档案中去,就可以这么写:『ls -l / > test 』,那个大于的符号『 > 』就是将输出结果导向到 test 这个档案中的意思啰!这个时候:

§ 如果你执行『 ls -l / 』而已的话,萤幕会将根目录的档案与目录都列出在萤幕上;

§ 但是当使用 > 导向到 test 这个档案中时,则萤幕不会显示任何讯息,但是会将刚刚你执行的结果输出到 test 这个档案中。

所以啰,你只要『 vi test 』一下,就会知道 test 这个档案中记录了刚刚我们执行的资料结果啰!不过,这里需要特别留意的是,当你使用 > 符号将资料由萤幕导向到档案中时,则:

§ 该档案(就是 test )若不存在,系统会自动的将他建立起来,但是,

§ 当这个档案存在的时候,那么系统就会先将这个档案内容清空,然后再将资料写入!

§ 也就是若以 > 输出到一个既存档案中,呵呵,那个档案就会被覆盖掉啰!

除了这个 > 的符号之外,在 bash 命令执行的过程中,主要有三种输出入的状况,分别是:

1. 标准输入;代码为 0 ;或称为 stdin ;使用的方式为 <

2. 标准输出:代码为 1 ;或称为 stdout;使用的方式为 1>

3. 错误输出:代码为 2 ;或称为 stderr;使用的方式为 2>

注意了!那个 1> 与 2> 之间并没有空白字元!而相关的使用说明可以举例如下

 

[test @test test]# ls -al > list.txt <==将显示的结果输出到 list.txt 档案中,若该档案以存在则予以取代! [test @test test]# ls -al >> list.txt <==将显示的结果累加到 list.txt 档案中,该档案为累加的,旧资料保留! [test @test test]# ls -al 1> list.txt 2> list.err <==将显示的资料,正确的输出到 list.txt 错误的资料输出到 list.err [test @test test]# ls -al 1> list.txt 2>&1 <==将显示的资料,不论正确或错误均输出到 list.txt 当中! [test @test test]# ls -al 1> list.txt 2> /dev/null<==将显示的资料,正确的输出到 list.txt 错误的资料则予以丢弃!注意!错误与正确档案输出到同一个档案中,则必须以上面的方法来写!不能写成其他格式!

这个观念相当的重要,尤其是在 /etc/crontab 当中执行的时候,如果我们已经知道错误的讯息为何,又不想要让错误的讯息一直填满 root 的信箱,就必须以 2> 搭配 /dev/null 这个垃圾桶黑洞装置,来将资料丢弃!这个相当的重要!

这里我们来说明一下命令重导向里面几个常用的符号与装置:

o < :由 < 的右边读入参数档案;

o > :将原本由萤幕输出的正确资料输出到 > 右边的 file ( 档案名称 ) 或 device ( 装置,如 printer )去;

o >> :将原本由萤幕输出的正确资料输出到 >> 右边,与 > 不同的是,该档案将不会被覆盖,而新的资料将以『增加的方式』增加到该档案的最后面;

o 2> :将原本应该由萤幕输出的错误资料输出到 2> 的右边去。

o /dev/null :可以说成是黑洞装置!

好了,对于『 > , >> 』这两个东西有一定的概念之后,我们来深入的谈一谈『命令输出重导向』的观念吧!如前所述,基本上, Linux 执行的结果中,可以约略的分成『正确输出』与『错误输出』两种方式。例如,当你以一般身份执行 find 这个指令时,例如执行『 find / -name testing 』时,由于你是一般身份,又有些资料夹是不允许一般身份者进入的,所以啰,当你使用 find 时,就会有错误讯息发生了!但同时如果有 testing 这个档案在你可以进入的资料夹当中,那么萤幕也会输出到给你看!因此,就具有正确的与错误的输出两种啰!(分别称为 Stdout 与 Stderror)例如下面为执行结果:里面的『 find: /home/root: Permission denied 』就告诉你该资料夹你没有权限进入,这就是错误的输出了,那么『 /home/test/tseting 』就是正确的输出了!

 

[test @test test]# find / -name testing find: /home/test1: Permission denied <==这是错误的输出 find: /home/root: Permission denied  <==这是错误的输出 find: /home/masda: Permission denied <==这是错误的输出 /home/test/testing<==这是『正确』的输出 [test @test test]#

好了,那么假如我们想要将资料输出到 list 这个档案中呢?执行『 find / -name testing > list 』会有什么结果?呵呵,你会发现 list 里面存了刚刚那个『正确』的输出资料,至于萤幕上还是会有错误的讯息出现呢!伤脑筋!如果想要将正确的与错误的资料分别存入不同的档案中需要怎么做?!呵呵!其实在资料的重导向方面,正确的写法应该是『 1> 』与『 2> 』才对!但是如果只有 > 则预设是以 1> 来进行资料的!那个 1> 是输出正确资料, 2> 则是错误资料输出项目。也就是说:

· 1> :是将正确的资料输出到指定的地方去

· 2> :是将错误的资料输出到指定的地方去

好了,那么上面的例子中,我们如何将资料输出到不同的地方去呢?可以这么写:

 

[test @test test]# find / -name testing 1> list_right 2> list_error

这样一来,刚刚执行的结果中,有 Permission 的那几行错误资讯都会跑到 list_error 这个档案中,至于正确的输出资料则会存到 list_right 这个档案中啰!这样可以了解了吗?如果有点混乱的话,去休息一下再来看看吧!!

再来,如果我只要正确的资料,错误的资讯我不要了呢?呵呵,这个时候 /dev/null 这个垃圾桶就很重要了!/dev/null 是什么呢?基本上,那就有点像是一个『黑洞』的垃圾桶功能!当你输入的任何东西导向到这个虚拟的垃圾桶装置时,『他就会凭空消失不见了~~』,这个东西有用的很!例如上面的例子中,我们可以这么做,来将错误的资讯丢掉!

 

[test @test test]# find / -name testing 1> list_right 2> /dev/null

很神奇呦! error message 就会『不见了!』呵呵!真高兴!另外,如果我要将资料都写到同一个档案中呢?这个时候写法需要用到特殊写法,请注意底下的写法呦!

 

[test @test test]# find / -name testing 1> list 2> list <==错误写法 [test @test tset]# find / -name testing 1> list 2>&1 <==正确写法

请特别留意这一点呢!同时写入同一个档案需要使用 2>&1 才对呦!

OK!了解了 >, 2>, >> 与 /dev/null 之后,那么那个 < 又是什么呀!?呵呵!以最简单的说法来说,那就是『将原本需要由键盘输入的资料,经由档案来读入』的意思,最明显的例子就是 mail 这个东西了!我们以 root 的身份来寄信给 root 好了,可以这样做:

 

1. 完全由键盘输入资料: [root @test test]# mail -s "test" root <== -s 表示标题, root 为收件者 I am root! <==以下的资料都是由键盘输入的 That's OK .   <==要结束键盘的输入时,需要在一行的最前面加上 . 即可! CC. <==是否需要有密件副本?不需要的话,直接按下 Enter ! EOF <==表示送出的提示字元而已! 2. 由档案代替输入 [test @test tset]# mail -s "test" root < /root/.bashrc <==将 .bashrc 内容寄给 root !

很有趣吧! ^_^ 这样就可以将信寄出去啰!所以说,熟悉命令重导像的话,对您可是相当的有帮助的呦!

好了,那么为何要使用命令输出重导向呢?这个问题一定会困扰你一下下的,如果你从来都没有写过 script 的话!好了,我们来说一说吧!

o 当萤幕输出的资讯很重要,而且我们需要将他存下来的时候;

o 背景执行中的程式,不希望他干扰萤幕正常的输出结果时;

o 一些系统的例行命令(例如写在 /etc/crontab 中的档案)的执行结果,希望他可以存下来时;

o 一些执行命令,我们已经知道他可能的错误讯息,所以想以『 2> /dev/null 』将他丢掉时;

o 错误讯息与正确讯息需要分别输出时。

当然还有很多很多的功能的,最简单的就是网友们常常

原文转自:http://www.ltesting.net