文章目录
- 一、认识 BASH 这个 Shell
- 二、Shell 的变量功能
- 三、命令别名与历史命令
- 四、Bash Shell 的操作环境
- 五、数据流重导向
- 六、管线命令 (pipe)
- 七、大总结
- 八、习题
1.硬件、核心与 Shell
(1)我们必须要透过『Shell 』将我们输入的指令与 Kernel 沟通,好让 Kernel 可以控制硬件来正确无误的工作! 基本上,我们可以透过底下这张图来说明一下:
2.为何要学文字接口的 shell?
(1)不同的 distribution 所设计的 X window 接口也都不相同,这样也造成学习方面的困扰。
文字接口的 shell 就不同了!几乎各家 distributions 使用的 bash 都是一样的!如此一来, 你就能够轻轻松松的转换不同的 distributions ,就像武侠小说里面提到的『一法通、万法通!』
(2)联机时文字接口的传输速度一定比较快, 而且,较不容易出现断线或者是信息外流的问题 .。
(3)由于学习 shell 的好处真的是多多啦!所以,如果你是个系统管理员,或者有心想要管理系统的话,那么 shell 与 shell scripts 这个东西真的有必要看一看!因为他就像『打通任督二脉,任何武功都能随你应用』的说!
3.系统有哪些shell?我使用哪个shell?
(1)那么目前我们的 Linux (以 CentOS 7.x 为例) 有多少我们可以使用的 shells 呢? 你可以检查一下/etc/shells 这个文件,至少就有底下这几个可以用的 shells :
(2)我这个使用者什么时候可以取得 shell 来工作呢?还有, 我这个使用者预设会取
得哪一个 shell 啊?
当我登入的时候,系统就会给我一个 shell 让我来工作了。 而这个登入取得的 shell 就记录在/etc/passwd 这个文件内!
4.Bash shell 的功能
(1)命令编修能力 (history):~/.bash_history
因为我只要在指令列按『上下键』就可以找到前/后一个输入的指令!
这么多的指令记录在哪里呢?在你的家目录内的 .bash_history 啦! 不过,需要留意的是,
~/.bash_history 记录的是前一次登入以前所执行过的指令, 而至于这一次登入所执行的指令都被暂存在内存中,当你成功的注销系统后,该指令记忆才会记录到 .bash_history 当中!
这有什么优点呢?最大的好处就是可以『查询曾经做过的举动!』
(2)命令与文件补全功能: ([tab] 按键的好处)
常常在 bash 环境中使用 [tab] 是个很棒的习惯喔!因为至少可以让你 1)少打很多字; 2)确定输入的数据是正确的!
(3)命令别名设定功能: (alias)
eg:lm 会等于 ls -al 这样的一个功能,嘿!那么要如何作呢?就使用 alias 即可!你可以在指令列输入 alias 就可以知道目前的命令别名有哪些了!也可以直接下达命令来设定别名呦:
(4)程序化脚本: (shell scripts)
以前在DOS 底下需要程序语言才能写的东西,在 Linux 底下使用简单的 shell scripts 就可以帮你达成了!
(5)通配符: (Wildcard)
eg:举例来说,想要知道 /usr/bin 底下有多少以 X 为开头的文件吗?使用:『ls -l /usr/bin/X* 』就能够知道啰
5.查询指令是否为 Bash shell 的内建命令: type
(1)在 shell 的环境下,直接输入man bash ,让你看个几天几夜也无法看完的 bash 说明文件。
(2)那我怎么知道这个指令是来自于外部指令(指的是其他非 bash 所提供的指令) 或是内建在 bash 当中的呢? 利用type
(3)type指令的说明如下:type 主要在找出 『指令』 而不是一般文件档名喔!
6.指令太长用反斜杠\
(1) 鸟哥这里仅就反斜杠 () 来说明一下指令下达的方式啰
(2)需要特别留意, [Enter] 按键是紧接着反斜杠 () 的,两者中间没有其他字符。 因为 \ 仅跳脱『紧接着的下一个字符』而已!
(3)总之,当我们顺利的在终端机 (tty) 上面登入后, Linux 就会依据 /etc/passwd 文件的设定给我们一个 shell (预设是 bash)。
二、Shell 的变量功能1.什么是变量?
(1)变量的定义
那么,什么是『变量』呢?简单的说,就是让某一个特定字符串代表不固定的内容就是了。
(2)变量的可变性与方便性
(3)影响 bash 环境操作的变量
- 你『真正以 shell 来跟 Linux 沟通,是在正确的登入 Linux 之后! 』这个时候你就有一
个 bash 的执行程序,也才可以真正的经由 bash 来跟系统沟通啰! - 而在进入 shell 之前,也正如同上面提到的,由于系统需要一些变量来提供他数据的存取 (或者是一些环境的设定参数值, 例如是否要显示彩色等等的) ,所以就有一些所谓的 『环境变量』 需要来读入系统中了!这些环境变量例如 PATH、 HOME、 MAIL、 SHELL 等等,都是很重要的, 为了区别与自定义变量的不同,环境变量通常以大写字符来表示呢!
(4)变量应用于 (shell script)
对于左图而言,如果下次换了一部主机,都要修改 script 里面的所有路径;
对于右图而言,这个时候如果使用变量,而将该变量的定义写在最前面,后面相关的路径名称都以变量来取代。
说明:最后我们就简单的对『什么是变量』作个简单定义好了:
『变量就是以一组文字或符号等,来取代一些设定或者是一串保留的数据!』
2.变量的取用与设定
(1)echo取用变量,用法:echo ${变量}
说明:
(i)变量的取用就如同上面的范例,利用 echo 就能够读出,只是需要在变量名称前面加上 $ , 或者是以 ${变量} 的方式来取用都可以!
(ii)eg
(2)修改变量的内容,用法:=
eg:设定一个变量myname,以及修改该变量的内容为VBird
注意:
每一种 shell 的语法都不相同~在变量的使用上, bash 在你没有设定的变量中强迫去 echo 时,它会显示出空的值。 在其他某些 shell 中,随便去 echo 一个不存在的变量,它是会出现错误讯息的喔!
(3)变量的设定规则
(i)
(ii)用下面的eg,结合着规则去看即可
说明:
(i)什么是『子程序』呢?
就是说,在我目前这个 shell 的情况下,去启用另一个新的 shell ,新的那个shell 就是子程序啦!在一般的状态下,父程序的自定义变量是无法在子程序内使用的。
(ii)但是透过export 将变量变成环境变量后,就能够在子程序底下应用了!
(iii)uname -r的使用
以 CentOS 7.1 (未更新前) 为例,他的预设核心版本是 3.10.0-229.el7.x86_64 ,所以核心模块目录在/lib/modules/3.10.0-229.el7.x86_64/kernel/ 内。
也由于每个 distributions 的这个值都不相同,但是我们却可以利用 uname -r 这个指令先取得版本信息。
所以啰,就可以透过上面指令当中的内含指令$(uname -r) 先取得版本输出到 cd … 那个指令当中,就能够顺利的进入目前核心的驱动程序所放置的目录啰!
(iiii)注意如何扩增环境变量的内容
(4)取消刚刚设定的 name 这个变量内容,用法:unset name
(5)其它的eg:单引号与双引号的区别
变量可以做目录简化功能!
3.环境变量的功能
(1)env:观察所有的环境变量(env是enviroment的缩写)
相关的环境变量的解释如下:
(2)set:观察所有的环境变量+自定义变量
解释说明:
(a)bash 可不只有环境变量喔,还有一些与 bash 操作接口有关的变量,以及用户自己定义的变量存在的。
(b)基本上,在 Linux 预设的情况中,使用{大写的字母}来设定的变量一般为系统内定需要的变量
(c)对于提示符的设定如下
eg:
(d)$: (关于本 shell 的 PID)
(e)?: (关于上个执行指令的回传值)
(f)32 位又可分为 i386, i586, i686,而 64 位则称为 x86_64。
(3)export:自定义变量转成环境变量
(a)父程序和子程序的关系
(i)当你登入 Linux 并取得一个 bash 之后,你的 bash 就是一个独立的程序,这个程序的识别使用的是一个称为程序标识符,被称为 PID 的就是。 接下来你在这个 bash 底下所下达的任何指令都是由这个 bash 所衍生出来的,那些被下达的指令就被称为子程序了。
(ii)我们可以用底下的图示来简单的说明一下父程序与子程序的概念:
(b)export的具体用法
(c)export没接变量,会将所有的环境变量显示出来
4.影响显示结果的语系变量 (locale)
(1)locale -a查看所有语系
(2)暂时修改语系
你有设定 LANG 或者是 LC_ALL 时,则其他的语系变量就会被这两个变量所取代!
(3)永久修改语系
整体系统默认的语系定义在哪里呢? 其实就是在 /etc/locale.conf
5.变量的有效范围
(1)在鸟哥的这个章节中,基本上你可以这样看待:
环境变量=全局变量
自定义变数=局部变量
(2)为什么环境变量的数据可以被子程序所引用呢?这是因为内存配置的关系!
- 当启动一个 shell,操作系统会分配一记忆区块给 shell 使用,此内存内之变量可让子程序取用
- 若在父程序利用 export 功能,可以让自定义变量的内容写到上述的记忆区块当中(环境变量);
- 当加载另一个 shell 时 (亦即启动子程序,而离开原本的父程序了),子shell 可以将父 shell 的环境变量所在的记忆区块导入自己的环境变量区块当中。
6.变量键盘读取、数组与宣告: read, array, declare
(1)read:读取来自键盘输入的变量
解释:
- read 之后不加任何参数,直接加上变量名称,那么底下就会主动出现一个空白行等待你的输入
- 如果加上 -t 后面接秒数,例如上面的范例二,那么 30 秒之内没有任何动作时, 该指令就会自动略过了
- 如果是加上 -p ,嘿嘿!在输入的光标前就会有比较多可以用的提示字符给我们参考
(2)declare / typeset
(a)declare 后面并没有接任何参数,那么 bash 就会主动的将所有的变量名称与内容通通叫出来
解释说明如下:
(b)将自定义变量转环境变量,将环境变量转自定义变量
补充:
比较有趣的是,如果你不小心将变量设定为『只读』,通常得要注销再登入才能复原该变量的类型了。
(c)在 bash 里头,数组的设定方式是:var[index]=content
7.与文件系统及程序的限制关系: ulimit(很少用)
(1)多用户同时访问,会考验内存容量。
我们的 bash 是可以『限制用户的某些系统资源』的,包括可以开启的文件数量, 可以使用的 CPU 时间,可以使用的内存总量等等。
如何设定?用 ulimit 吧!
补充:
利用 ulimit -f来限制使用者可以建立的文件大小。例如上面的范例二,要注意单位喔!单位是 Kbytes。
(2)想要复原 ulimit 的设定最简单的方法就是注销再登入,否则就是得要重新以 ulimit 设定才行!
8.变量里的内容的删除、取代与替换
(1)变量内容的删除
方法1从前面开始删除变量内容:用的多
补充:
(a)因为在 PATH 这个变量的内容中,每个目录都是以冒号『:』隔开的, 所以要从头删除掉目录就是介于斜线 (/) 到冒号 (: ) 之间的数据。
(b)但是 PATH 中不止一个冒号 (: ) 啊! 所以 # 与 ## 就分别代表:
方法2从后面向前删除变量内容:用的少
这个时候就得使用百分比 (%) 符号了!
eg:
(2)变量内容的取代
(1)变量内容的删除和(2)变量内容的取代的总结如下:
(3)变量的测试与内容替换
在某些时刻我们常常需要『判断』某个变量是否存在,若变量存在则使用既有的设定,若变量不存在则给予一个常用的设定。
(a)
补充:重点在于减号『- 』后面接的关键词的理解
(b)若username 可能已经被设定为『空字符串』,还可以使用底下的范例来给予 username 的内容成为 root。
说明:
在大括号内有没有冒号『: 』的差别是很大的!加上冒号后,被测试的变量未被设定或者是已被设定为空字符串时, 都能够用后面的内容 (本例中是使用 root 为内容) 来替换与设定!
(c)特别提醒echo “${}”
如果旧变量 (str) 不存在时, 我们要给予新变量一个内容,若旧变量存在则新变量内容以旧变量来替换。
(3)变量的测试与内容替换总结如下:
1.但是在 Linux 里面, 我们则是使用 clear 来清除画面的
2.命令别名设定: alias, unalias
(1)定义规则如下:
『alias 的定义规则与变量定义规则几乎相同』, 所以你只要在 alias 后面加上你的 {『别名』 =‘指令 选项…’ }
(2)eg1:如果你要查询隐藏档,并且需要长的列出与一页一页翻看,那么需要下达『ls -al | more 』这个指令。那可不可以使用 lm 来简化呢?
(3)eg2:
(3)目前有哪些的命令别名呢?就使用 alias 呀!
(4)至于如果要取消命令别名的话,那么就使用 unalias 吧
3.历史命令: history
(1)我们来谈一谈 history 的用法如下:
(2)在正常的情况下,历史命令的读取与记录是这样的:
(3)同一账号同时多次登入的 history 写入问题
因为等到注销时才会更新记录文件,所以啰, 最后注销的那个 bash 才会是最后写入的数据.
(4)无法记录时间
历史命令还有一个问题,那就是无法记录指令下达的时间。
其实可以透过~/.bash_logout 来进行 history 的记录,并加上 date 来增加时间参数,也是一个可以应用的方向喔!
1.路径与指令搜寻顺序
(1)基本上,指令运作的顺序可以这样看:
eg:你可以下达 /bin/ls 及单纯的 ls 看看,会发现使用 ls 有颜色但是 /bin/ls 则没有颜色。
因为 /bin/ls 是直接取用该指令来下达,而 ls 会因为『alias ls=‘ls --color=auto’ 』这个命令别名而先使用!
(2)了解指令搜寻的顺序,可透过type -a
eg1:想要了解指令搜寻的顺序,其实透过 type -a ls 也可以查询的到
eg2:
2.bash 的进站与欢迎讯息(进虚拟机最先显示的画面): /etc/issue, /etc/motd
(1)issue 这个文件的内容也是可以使用反斜杠作为变量取用喔!
eg:
(2)除了 /etc/issue 之外还有个 /etc/issue.net 呢!
这个是提供给 telnet 这个远程登录程序用的。 当我们使用 telnet 连接到主机时,主机的登入画面就会显示 /etc/issue.net 而不是/etc/issue 呢!
(3)至于如果您想要让使用者登入后取得一些讯息,例如您想要让大家都知道的讯息, 那么可以将讯息加入 /etc/motd 里面去!(一定要用 root 的身份才能修改喔! )
3.bash 的环境配置文件
(1)login 与 non-login shell的区别
(2)一般来说,login shell 其实只会读取这两个配置文件
(a)/etc/profile (login shell 才会读)
每个使用者登入取得 bash 时一定会读取的配置文件!这个文件设定的变量主要有:
(b)~/.bash_profile (login shell 才会读)
eg:首先看下.bash_profile 的内容
你可以将自己建立的执行档放置到你自己家目录下的 ~/bin/ 目录啦! 那就可以直接执行该执行档而不需要使用绝对/相对路径来执行该文件。
最后,我们来看看整个 login shell 的读取流程:
(3)source :读入环境配置文件的指令
(4)~/.bashrc (non-login shell 会读)
当你取得 non-login shell 时,该 bash 配置文件仅会读取 ~/.bashrc 而已啦!
说明:
(i)由于 root 的身份与一般使用者不同,鸟哥是以 root 的身份取得上述的数据, 如果是一般使用者的 ~/.bashrc 会有些许不同
(ii)此外,咱们的 CentOS 7.x 还会主动的呼叫 /etc/bashrc 这个文件喔!why?
因为 /etc/bashrc 帮我们的 bash 定义出底下的数据:
所以,万一你没有 ~/.bashrc (可能自己不小心将他删除了),那么你会发现你的bash 提示字符可能会变成这个样子:
(5)/etc/man_db.conf:这个文件规定了下达 man 的时候,该去哪里查看数据的路径设定
(6)~/.bash_history
预设的情况下, 我们的历史命令就记录在这里啊!
(7)~/.bash_logout
你可以去读取一下这个文件的内容,预设的情况下,注销时, bash 只是帮我们清掉屏幕的讯息而已。
4.终端机的环境设定: stty, set
(1)stty:查阅目前的一些按键内容
说明:
(i)如果出现 ^ 表示 [Ctrl] 那个按键的意思。
(ii)
(iii)常用组合键(一般不要修改这些组合键)
5.通配符与特殊符号
(1)一些常用的通配符:
(2)接下来让我们利用通配符来玩些东西吧!首先,利用通配符配合 ls 找檔名看看
(3)bash 环境中的特殊符号有哪些呢?
1.什么是数据流重导向
数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到其他的地方。
(1)数据流重导向的作用
数据流重导向可以将 standard output(简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符则如下所示:
(2)输出的分类
(a)standard output 中的>作用
解释说明如下:
rootfile文件建立方式是:
(b)standard output 中的>>作用
那如果我想要将数据累加而不想要将旧的数据删除,那该如何是好?利用两个大于的符号 (>>) 就好啦!
eg:ll / >> ~/rootfile
(c)standard output 中的>和>>作用
(3)总结输出方式
(4)将错误讯息忽略掉而不显示或存储:/dev/null
(5)将正确与错误数据通通写入同一个文件去
(6)standard input : < 与 <<
(a)cat新建一个由键盘输入的文件
(b)cat新建一个由其他文件输入的文件
说明:
<< 代表的是『结束的输入字符』,利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束哩!
(7)eg
2.命令执行的判断依据: ; , &&, ||
Linux 底下的指令都是由左往右执行
(1)cmd ; cmd (不考虑指令相关性的连续指令下达)
eg:在关机的时候我希望可以先执行两次 sync 同步化写入磁盘后才 shutdown 计算机
在指令与指令中间利用分号 ( ; ) 来隔开,这样一来,分号前的指令执行完后就会立刻接着执行后面的指令了。
(2)$? (指令回传值) 与 && 或 ||
(a)若前一个指令执行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值
(b)直接看eg
看到了吧?如果 /tmp/abc 不存在时, touch 就不会被执行,若 /tmp/abc 存在的话,那么 touch 就会
开始执行啰!
整个流程图示如下:
eg:
- command1 若能执行,则${?}=0,那么command2就会执行,这俩执行完的结果是 ${?}=0,command3则不会执行;
- command1 若不能执行,则${?}=1,那么command2就不会执行,这俩执行完的结果是 ${?}=1,command3则会执行;
- 总结来说,&&
1.管线命令的处理要求
(1)每个管线后面接的第一个数据必须要能够接受 standard input 的数据才行。例如 less, more, head, tail 等都是可以接受 standardinput 的管线命令啦。
(2)
(3)如果你硬要让 standard error 可以被管线命令所使用,咋办?
让 2>&1 加入指令中~就可以让 2> 变成 1>
2.撷取命令: cut, grep:都是一行一行分析的
(1)cut:按行分解数据
(2)cut用途:
cut 主要的用途在于将『同一行里面的数据进行分解!』最常使用在分析一些数据或文字数据的时候。不过, cut 在处理多空格相连的数据时,可能会比较吃力一点,所以某些时刻可能会使用下一章的 awk 来取代的!
(3)grep:分析一行数据
(4)grep用途
用在正规表示法里头, 能够处理的数据实在是多的很。
另外, CentOS 7 当中,预设的 grep已经主动加上 --color=auto 在 alias 内了喔!
2.排序命令: sort, wc, uniq
(1)sort:可以依据不同的数据形态来排序
(2)uniq:想要将重复的资料仅列出一个显示,但需要配合sort使用
(3)wc:如果我想要知道 /etc/man_db.conf 这个文件里面有多少字?多少行?多少字符?
3.双向重导向: tee
(1)tee 会同时将数据流分送到文件去与屏幕 (screen)
(2)tee 可以让 standard output 转存一份到文件内并将同样的数据继续送到屏幕去处理!
4.字符转换命令: tr, col, join, paste, expand
(1)tr:可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换
^M表示tab
去掉dos换行符的2种方法
这个时候除了以前讲过的 dos2unix 之外,我们也可以使用这个 tr 来将 ^M 去除! ^M 可以使用 \r 来代替之!
(2)col:简单的处理将 [tab] 按键取代成为空格键
^I表示tab
如果使用 cat -A 则 [tab] 会以 ^I 来表示。 但经过 col -x 的处理,则会将 [tab]取代成为对等的空格键。
(3)join:两个文件当中,第一个字段有 “相同数据” 的那一行,才将他加在一起(两个文件需要具有相关性)
说明:
- 例如上面的案例当中,我的/etc/passwd, /etc/shadow, /etc/group 都是有相关性的, 其中/etc/passwd, /etc/shadow 以账号为相关性
- 在使用 join 之前,你所需要处理的文件应该要事先经过排序 (sort) 处理
(4)paste:paste 就直接将两行贴在一起,且中间以 [tab] 键隔开(两个文件不需要具有相关性)
有-的使用
(5)expand:将 [tab] 按键转成空格键
说明:
(6)split:可以将大文件分区成为小文件
有-的使用
7.关于减号-的使用
该 stdin 与 stdout 可以利用减号 "-"来替代, 举例来说:
(1)由于核心在内存中是受保护的区块,因此我们必须要透过『Shell 』将我们输入的指令与 Kernel 沟通,好让 Kernel 可以控制硬件来正确无误的工作
(2)学习 shell 的原因主要有:文字接口的 shell 在各大 distribution 都一样;远程管理时文字接口速度较快;
shell 是管理 Linux 系统非常重要的一环,因为 Linux 内很多控制都是以 shell 撰写的。
(3)系统合法的 shell 均写在 /etc/shells 文件中;
(4) 用户默认登入取得的 shell 记录于 /etc/passwd 的最后一个字段;
(5)bash 的功能主要有:命令编修能力;命令与文件补全功能;命令别名设定功能;工作控制、前景背景控制;程序化脚本;通配符
(6)type 可以用来找到执行指令为何种类型,亦可用于与 which 相同的功能;
(7) 变量就是以一组文字或符号等,来取代一些设定或者是一串保留的数据
(8)变量主要有环境变量与自定义变量,或称为全局变量与局部变量
(9)使用 env 与 export 可观察环境变量,其中 export 可以将自定义变量转成环境变量;
(10)set 可以观察目前 bash 环境下的所有变量;
(11) $? 亦为变量,是前一个指令执行完毕后的回传值。在 Linux 回传值为 0 代表执行成功;
(12) locale 可用于观察语系资料;
(13) 可用 read 让用户由键盘输入变量的值
(14) ulimit 可用以限制用户使用系统的资源情况
(15) bash 的配置文件主要分为 login shell 与 non-login shell。 login shell 主要读取 /etc/profile 与 ~/.bash_profile,
non-login shell 则仅读取 ~/.bashrc
(16)在使用 vim 时,若不小心按了 [crtl]+s 则画面会被冻结。你可以使用 [ctrl]+q 来解除冻结
(17)通配符主要有: *, ?, [] 等等
(18) 数据流重导向透过 >, 2>, < 之类的符号将输出的信息转到其他文件或装置去;
(19) 连续命令的下达可透过 ; && || 等符号来处理
(20) 管线命令的重点是:『管线命令仅会处理 standard output,对于 standard error output 会予以忽略』 『管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理才行。』
(21) 本章介绍的管线命令主要有: cut, grep, sort, wc, uniq, tee, tr, col, join, paste, expand, split, xargs 等。