四、Bash shell的操作环境

1.路径与命令查找顺序

如果一个命令被下达时,到底是是哪一个同名的命令来运行呢?基本上,命令运行顺序如下所示:

(1)以相对/绝对路径执行指令,例如『/bin/ls』或『./ls』;

(2)由alias找到该指令来执行;

(3)由bash内建的(builtin)指令来执行;

(4)通过$PATH这个变量的顺序搜寻到的第一个指令来执行。

2.bash的登录与欢迎信息:/etc/issue, /etc/motd

打开/etc/issue就可以看到登录界面信息,比如我的写的就是:Ubuntu 18.04 LTS \n \l。issue里面各代码的涵义如下:

issue内的代码各代码意义
\d本地端时间的日期。
\l显示第几个终端机接口。
\m显示硬件的等级(i386/i486/i586/i686…)
\n显示主机的网络名称
\O显示 domain name
\r操作系统的版本 (相当于 uname -r)
\t显示本地端时间的时间
\S操作系统的名称
\v操作系统的版本

还有一个是/etc/issue.net,这个是提供给telnet远程登录程序的。如果想要让使用者登录以后获取一些信息,可以将信息加入到/etc/motd里面去。

3.bash的环境配置文件

系统有一些环境配置文件案的存在,让bash在启动时直接读取这些配置文件,以规划好bash的操作环境,而这些配置文件又可以分为全体系统的配置文件以及用户个人偏好配置文件。要注意的是,我们前几个小节谈到的命令别名啦、自定义变量啦,在你注销bash后就会失效,所以你想要保留你的设定,就得要将这些设定写入配置文件才行。

(1)login shell与non-login shell

login shell:取得bash时需要完整的登录流程的,就称为login shell。举例来说,你要由tty1~tty6登入,需要输入用户的账号与密码,此时取得的bash就称为“login shell”。

non-login shell:取得 bash界面的方法不需要重复登录的操作。

因为这两个取得bash的情况中,读取的配置文件数据并不一样,所以需要介绍一下这两个shell。

login shell读取这两个配置文件:

①/etc/profile:这是系统整体的配置,你最好不要修改这个文件;

②~/.bash_profile或~/.bash_login或~/.profile:属于使用者个人设定,你要改自己的数据,就写入这里。

(2)/etc/profile(只有login shell才会读取)

这个配置文件可以利用用户的标识符(UID)来决定很多重要的变量数据,这也是每个用户登入取得bash时一定会读取的配置文件。所以如果你想要帮所有用户配置整体环境,那就是改这里。不过,尽量不要修改这个配置文件。这个文件配置的变量主要有

PATH依据UID决定PATH变量是否含有sbin的系统命令目录。
MAIL依据帐号设定好用户的mailbox到/var/spool/mail/帐户名。
USER根据用户的帐号设置此变量内容。
HOSTNAME根据主机的hostname决定这个变量内容。
HISTSIZE历史命令记录的个数。
umask包括root预设为022,一般用户为002。

除了以上之外,该文件还会去调用外部的配置文件。在CentOS 7.x的默认配置下,会依次调用以下文件:

①/etc/profile.d/*.sh;

②/etc/locale.conf

③/usr/share/bash-completion/completions/*

bashlogin shell情况下所读取的整体环境配置文件其实只有/etc/profile

(3)~/.bash_profile(login shell才会读取)

在login shell的bash环境中,所读取的个人偏好配置文件其实主要有三个,依序分别是

①~/.bash_profile

②~/.bash_login

③~/.profile

其实 bash的login shell设定只会读取上面三个文件中的一个,而读取的顺序则是依照上面的顺序。

最后看一下整个login shell的读取流程:

图4.1 login shell读取流程

(4)source:读入环境配置文件的命令

由于/etc/profile与~/.bash_profile都是在取得loginshell的时候才会读取的配置文件,所以,如果你将自己的偏好设定写入上述的文件后,通常都是得注销再登入后,该设定才会生效。那么,能不能直接读取配置文件而不注销登入呢?可以的!那就得要利用source这个指令了。

命令使用格式如下:

[dmtsai@study ~]$ source 配置文件的文件名

利用source或小数点(.)都可以将配置文件的内容读进来目前的shell环境中。

(5)~/.bashrc(non-login shell读取的配置文件)

当读取non-login shell的时候,该bash仅仅会读取~/.bashrc这个配置文件。

(6)其他相关配置文件

①/etc/man_db.conf:规范了使用man的时候,man page的路径到哪里去寻找。

②~/.bash_history。

③~/.bash_logout:当退出bash后,系统完成什么操作后再离开。

4.终端机的环境设置:stty,set

如何查阅目前的一些按键内容呢?可以利用stty(settingtty终端机的意思)呢!stty也可以帮助设定终端机的输入按键代表意义。

[dmtsai@study ~]$ stty [-a]

选项与参数:

-a:将目前所有的stty参数列出来。

下面举一个例子

[dmtsai@study ~]$ stty -a

speed 38400 baud; rows 20; columns 90; line = 0;

intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;

swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;

flush = ^O; min = 1; time = 0;

 

几个重要的代表意义是:

①intr:送出一个interrupt(中断)的信号给目前正在run的程序;

②quit:送出一个quit的信号给目前正在run的程序;

③erase:向后删除字符,

④kill:删除在目前指令列上的所有文字;

⑤eof:Endoffile的意思,代表『结束输入』。

⑥start:在某个程序停止后,重新启动他的output

⑦stop:停止目前屏幕的输出;

⑧susp:送出一个terminalstop的信号给正在run的程序。

bash还有自己的一些终端机预设值,使用set来设置。set能够显示变量,还能够棒我们设置整个命令输入/输出环境。

[dmtsai@study ~]$ set [-uvCHhmBx]

选项与参数:

-u:预设不启用。若启用后,当使用未设定变量时,会显示错误信息;

-v:预设不启用。若启用后,在信息被输出前,会先显示信息的原始内容;

-x:预设不启用。若启用后,在指令被执行前,会显示指令内容(前面有++符号)

-h:预设启用。与历史命令有关;

-H:预设启用。与历史命令有关;

-m:预设启用。与工作管理有关;

-B:预设启用。与中括号[]的作用有关;

-C:预设不启用。若使用>等,则若文件存在时,该文件不会被覆盖。

最后整理一下bash里面的快捷键及功能

组合按键执行结果
Ctrl+C终止目前的命令
Ctrl+D输入结束(EOF),例如邮件结束的时候;
Ctrl+M就是Enter啦!
Ctrl+S暂停屏幕的输出
Ctrl+Q恢复屏幕的输出
Ctrl+U在提示字符下,将整列命令删除
Ctrl+Z『暂停』目前的命令

 

5.通配符与特殊符号

通配符如下表所示。

符号意义
*代表0个到无穷多个任意字符
?代表一定有一个任意字符
[]同样代表『一定有一个在括号内』的字符(非任意字符)。例如[abcd]代表『一定有一个字符,可能是a,b,c,d这四个任何一个』
[-]若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如[0-9]代表0到9之间的所有数字,因为数字的语系编码是连续的!
[^]若中括号内的第一个字符为指数符号(^),那表示『反向选择』,例如[^abc]代表一定有一个字符,只要是非a,b,c的其他字符就接受的意思。

特殊符号如下

符号内容
#批注符号:这个最常被使用在script当中,视为说明!在后的数据均不执行
\转义符号:将『特殊字符或通配符』还原成一般字符
|管线(pipe):分隔两个管线命令的界定(后两节介绍);
;连续指令下达分隔符:连续性命令的界定(注意!与管线命令并不相同)
~用户的家目录
$取用变数前导符:亦即是变量之前需要加的变量取代值
&工作控制(jobcontrol):将指令变成背景下工作
!逻辑运算意义上的『非』not的意思!
/目录符号:路径分隔的符号
>,>>数据流重导向:输出导向,分别是『取代』与『累加』
<,<<数据流重导向:输入导向(这两个留待下节介绍)
单引号,不具有变量置换的功能($变为纯文本)
“”具有变量置换的功能!($可保留相关功能)
两个『』中间为可以先执行的指令,亦可使用$()
( )在中间为子 shell 的起始与结束
{ }在中间为命令区块的组合!

 

五、数据流复位向

数据流复位向就是将某个命令执行后应该要出现在屏幕上的数据传输到其他地方去。

standard output(标准输出)指的是命令执行所回传的正确信息。standard error output(标准错误输出)指的是命令执行失败后,所回传的错误信息

不管正确还是错误的数据都是预设输出到屏幕上。可以通过数据复位向将标准输出(stdout)和标准错误输出(stderr)分别传送到其它文件或设备中区。而所传输的特殊字符如下所示:

①标准输入(stdin):代码为0,使用<或<<;

②标准输出(stdout):代码为1,使用>或>>;

③标准错误输出(stderr):代码为2,使用2>或2>>。

关于标准输出和标准错误输出还有以下要说明的:

①1>:以覆盖的方法将『正确的数据』输出到指定的文件或设备上;

②1>>:以累加的方法将『正确的数据』输出到指定的文件或设备上;

③2>:以覆盖的方法将『错误的数据』输出到指定的文件或设备上;

④2>>:以累加的方法将『错误的数据』输出到指定的文件或设备上。

如果我知道错误信息会发生,所以要将错误信息忽略掉而不显示或者储存该如何去做呢?这个时候/dev/null就很重要的,正如null所表达的。例如下:

[dmtsai@study ~]$ find /home -name .bashrc 2> /dev/null

如果我们先将正确和错误的信息统统写入到同一个文件呢?是不是可以这样呢?

[dmtsai@study ~]$ find /home -name .bashrc > list 2> list

答案是不行的 ,因为由于两段数据同时写入一个文件,又没有使用特殊的语法,此时两段数据可能会交叉写入该文件内,造成次序的错乱。因此,可以使用下面的语法:2>&1,或者&>!。一般情况下,用前者。

standard input是指将原本需要由键盘输入的数据,改由文件内容来输入。如果我们用cat直接将输入的信息输出的catfile中,且当由键盘输入eof时,该次输入就结束。例如

[dmtsai@study ~]$ cat > catfile << "eof"

> This is a test.

> OK now stop

> eof  <==输入这关键词,立刻就结束而不需要输入 [ctrl]+d

 

[dmtsai@study ~]$ cat catfile

This is a test.

OK now stop     <==只有这两行,不会存在关键词那一行!

利用<<右侧的控制字符,我们可以终止一次输入,而不必输入[ctrl]+d来结束。

什么时候需要使用数据流复位向呢?如下:

①屏幕输出的信息很重要,而且我们需要将他存下来的时候;

②后台执行中的程序,不希望他干扰屏幕正常的输出结果时;

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

④一些执行命令的可能已知错误信息时,想以『 2> /dev/null 』将他丢掉时;

⑤错误信息与正确信息需要分别输出时。

1.命令执行的判断依据:;,&&||

(1)cmd;cmd

利用;可以不考虑指令的相关性连续下达指令。

(2)$?(命令回传值)与&&或||

指令下达情况说明
cmd1&&cmd21.若cmd1执行完毕且正确执行($?=0),则开始执行cmd2。
2.若cmd1执行完毕且为错误($?≠0),则cmd2不执行。
cmd1||cmd21.若cmd1执行完毕且正确执行($?=0),则cmd2不执行。
2.若cmd1执行完毕且为错误($?≠0),则开始执行cmd2。

在Linux下,若执行成功回传0,否则回传非0。

由于指令是一个接着一个去执行的,因此,如果真要使用判断, 那么这个 && || 的顺序就不能搞错

格式为:

command1 && command2 || command3

六、管道命令

管道命令使用的是“|”这个界定符号,这个命令与连续执行命令是不一样的!

管道命令仅能够处理经由前面一个命令传来的正确信息,也就是standard output的信息,对于standard error并没有直接处理的能力。因此其示意图如下所示。

图6.1 管道命令的处理示意图

在每个管道后面接的第一个数据必定是『命令』。而且这个命令必须要能够接受standard input的数据才行,这样的指令才可以是为『管线命令』。

如果你硬要让standard error可以被管线命令所使用,那该如何处理?其实就是透过上一小节的数据流重导向即可!让2>&1加入指令中~就可以让2>变成1>啰!

1.选取命令:cutgrep

将一段数据经过分析后,取出我们想要的,或者经由关键字分析,取出我们想要的那行。要注意,选取信息通常针对逐行来分析。

(1)cut

[dmtsai@study ~]$ cut -d'分隔字符' -f fields <==用于有特定分隔字符

[dmtsai@study ~]$ cut -c 字符区间            <==用于排列整齐的信息

选项与参数:

-d:后面接分隔字符。与-f一起使用;

-f:依据-d的分隔字符将一段讯息分割成为数段,用-f取出第几段的意思;

-c:以字符(characters)的单位取出固定字符区间。

举例如下:


图6.2 示例用法

cut主要的用途在于将『同一行里面的数据进行分解!』最常使用在分析一些数据或文字数据的时候!这是因为有时候我们会以某些字符当作分割的参数,然后来将数据加以切割,以取得我们所需要的数据。

(2)grep是分析一行信息,若当中有我们需要的信息,则将该行拿出来。使用方法如下所示:

[dmtsai@study ~]$ grep [-acinv] [--color=auto] '搜索字符串' filename

选项与参数:

-a:将binary文件以text文件的方式搜寻数据

-c:计算找到'搜寻字符串'的次数

-i:忽略大小写的不同,所以大小写视为相同

-n:顺便输出行号

-v:反向选择,亦即显示出没有'搜寻字符串'内容的那一行!

--color=auto:可以将找到的关键词部分加上颜色的显示喔!

 

2.排序命令:sortwcuniq

(1)sort

[dmtsai@study ~]$ sort [-fbMnrtuk] [file or stdin]

选项与参数:

-f:忽略大小写的差异,例如A与a视为编码相同;

-b:忽略最前面的空格符部分;

-M:以月份的名字来排序,例如JAN,DEC等等的排序方法;

-n:使用『纯数字』进行排序(默认是以文字型态来排序的);

-r:反向排序;

-u:就是uniq,相同的数据中,仅出现一行代表;

-t:分隔符,预设是用[tab]键来分隔;

-k:以那个区间(field)来进行排序的意思。

(2)uniq

[dmtsai@study ~]$ uniq [-ic]

选项与参数:

-i:忽略大小写字符的不同;

-c:进行计数。

这个指令用来将『重复的行删除掉只显示一个』。

(3)wc:显示文件有多少行,多少字符等。

[dmtsai@study ~]$ wc [-lwm]

选项与参数:

-l:仅列出行;

-w:仅列出多少字(英文单字);

-m:多少字符。

 

3.双向复位向:tee

tee的工作流程示意图如下图所示。

图6.3 tee的工作流程示意图

使用方法如下所示。

[dmtsai@study ~]$ tee [-a] file

选项与参数:

-a:以累加(append)的方式,将数据加入file当中。

 

4.字符转换命令:trcoljoinpasteexpand

(1)tr可以用来删除一段信息当中的文字,或者是进行文字信息的替换。

[dmtsai@study ~]$ tr [-ds] SET1 ...

选项与参数:

-d:删除讯息当中的SET1这个字符串;

-s:替换掉重复的字符!

(2)col

[dmtsai@study ~]$ col [-xb]

选项与参数:

-x:将tab键转换成对等的空格键

(3)join

处理『两个文件当中,有 "相同数据" 的那一行,才将他加在一起』。

[dmtsai@study ~]$ join [-ti12] file1 file2

选项与参数:

-t:join默认以空格符分隔数据,并且比对『第一个字段』的数据,如果两个文件相同,则将两笔数据联成一行,且第一个字段放在第一个!

-i:忽略大小写的差异;

-1:这个是数字的1,代表『第一个文件要用那个字段来分析』的意思;

-2:代表『第二个文件要用那个字段来分析』的意思。

(4)paste:两行连着一起,中间以TAB隔开。

[dmtsai@study ~]$ paste [-d] file1 file2

选项与参数:

-d:后面可以接分隔字符。预设是以[tab]来分隔的!

-:如果file部分写成-,表示来自standard input的资料的意思。

(5)expand:将TAB按键转换成空白键。

[dmtsai@study ~]$ expand [-t] file

选项与参数:

-t:后面可以接数字。一般来说,一个tab按键可以用8个空格键取代。

我们也可以自行定义一个[tab]按键代表多少个字符。

 

5.分割命令:split

split将大文件分割为小文件。使用方法如下。

[dmtsai@study ~]$ split [-bl] file PREFIX

选项与参数:

-b:后面可接欲分割成的文件大小,可加单位,例如b,k,m等;

-l:以行数来进行分割。

PREFIX:代表前导符的意思,可作为分割文件的前导文字。

 

6.参数替代:xargs

xargs可以读入stdin的数据,并且以空格符或断行字符作为分辨,将stdin的资料分隔成为arguments。

[dmtsai@study ~]$ xargs [-0epn] command

选项与参数:

-0:如果输入的stdin含有特殊字符,例如,\,空格键等等字符时,这个-0参数可以将他还原成一般字符。这个参数可以用于特殊状态;

-e:这个是EOF(endoffile)的意思。后面可以接一个字符串,当xargs分析到这个字符串时,就会停止继续工作;

-p:在执行每个指令的argument时,都会询问使用者的意思;

-n:后面接次数,每次command指令执行时,要使用几个参数的意思。

xargs后面没有接任何的指令时,默认是以echo来进行输出。

 

7.关于减号的用途

在管道命令当中,常常会使用到前一个指令的stdout作为这次的stdin,某些指令需要用到文件名来进行处理时,该stdin与stdout可以利用减号”-“来替代,举例来说:

[root@study ~]# mkdir /tmp/homeback

[root@study ~]# tar -cvf – /home | tar -xvf – -C /tmp/homeback

上面这个例子是说:『我将/home里面的文件给他打包,但打包的数据不是记录到文件,而是传送到stdout;经过管道后,将tar-cvf-/home传送给后面的tar-xvf-』。后面的这个-则是取用前一个指令的stdout,因此,我们就不需要使用filename了。