1.认识BASH这个Shell
操作系统的内核管理着整个计算机硬件,它是需要被保护的,所以一般用户只能通过Shell和内核交流。
1.1 硬件,内核与Shell
Shell是我们与内核沟通的工具,我们必须通过Shell将我们输入的命令与内核沟通,好让内核可以控制硬件来正确无误的工作。
1.2 为什么要学习命令行模式的Shell?
- 命令行模式的Shell:大家都一样
几乎各家的Linux发行版使用的bash都是一样的。如此一来,就可以轻松转换不同的Linux发行版。 - 远程管理:命令行模式就是比较快
Linux的管理常常需要通过远程联机,而联机时命令行模式的传输速度一定比较快,而且不容易出现掉线或者信息外流的问题。 - 管理Linux必备
真心想要学习Linux,想要将主机管理好,良好的shell程序编写和一定需要的。
1.3 Bash shell的功能
Bash是Linux默认的shell,它是Linux发行版的标准shell,有许多优点:
- 历史命令
只要在命令行里按上下键就可以找到前后一个输入命令。 - 命令与文件补全功能
【Tab】接在一串命令的第一个字后面,则为命令补全。
【Tab】接在一串命令的第二个字后面,则为【文件补全】。 - 命令别名设置功能(alias)
alias 自定义命令名='系统命令'
1.5 查询命令是否为Bash shell的内置命令:type
bash中已经内置了许多命令,通过type命令可以得到命令是来自于外部还是内置在bash中。
type [-tpa] name
不加任何选项与参数时,type会显示出name是外部命令还是bash内置命令。
-t :当加入-t参数时,type将name以下面这些字眼显示出它的意义。
file :表示为外部命令。
alias :表示该命令为命令别名所设置的名称。
builtin :表示该命令为bush内置的命令功能。
-p :如果后面接的name为外部命令时,才会显示完整文件名。
-a :会由PATH变量定义的路径中,将所有含name的命令都列出来,包括alias。
1.6 命令的指定与快速编辑功能
当一段命令过长,想要换行编写时,可以使用\[Enter]的方式换行,利用\是[Enter]不在具有开始执行的功能,注意\和[Enter]是紧接着的。
当使用\[Enter]进行转义成功时,会在下一行产生一个 > 的符号,就可以积继续输入命令。
另外,当你需要执行的命令特别长时,或者输入了一串错误的命令时,想要快速删除,也有快捷命令。
| 组合键 | 功能和示范 |
|---|---|
[ctrl]+u/[ctrl]+k |
分别是在光标处向前删除命令串([ctrl]+u)或向后删除命令串([ctrl]+k) |
[ctrl]+a/[ctrl]+e |
分别是让光标移动到整个命令串的最前面([ctrl]+a)或最后面([ctrl]+e) |
2. Shell的变量功能
Linux是多人多任务的环境,每个人登陆系统时都能取得一个bash shell,bash正是通过变量来辨别
2.1 什么是变量?
变量就是使用一个简单的字眼来替换另一个比较复杂或者是容易变动的数据。
- 变量的可变性与方便性
以邮箱MAIL举例,每个账号的邮箱默认是以MAIL这个变量来存储。
当user1登陆时,它的变量MAIL就是/var/spool/mail/user1,而当user2登陆时,它的变量MAIL就是var/spool/mail/user2。如此一
来,各个用户在使用mail命令时,mail就会获取这个用户自己的MAIL,用户就能得到自己的邮箱。
- 影响bash环境操作的变量
某些特定变量会影响到bash的环境。由在Linux中,只有在正确的登陆Linux之后,才能真正以shell来跟Linux沟通。 而在登陆Linux时,系统会依赖一组变量来确认用户身份,并为其构建独特的工作环境,这些变量就是环境变量。 - 脚本程序设计的好帮手
以上为系统默认的变量的目的,当进行个人应用时,比如设计脚本时,很多数据会根据用户环境的不同而有差异,例如路径,假设该路径在脚本中被使用了多次,当更换工作环境时,所有路径都需要修改,工作量相当大。而如果使用变量,只需在最前边定义一个变量为此路径,在之后的试用中通通使用此变量,则只需更改最前面的变量就可以修改整个脚本,十分方便。
变量就是以一组文字或符号等,来替换一些设置或一串保留的数据。
2.2 变量的使用和设置:echo,变量设置规则,unset
echo这个命令就是用来使用变量的,变量在使用时,前面必须加入美元符号【$】 。
变量的使用:
echo $PATH(使用后会显示PATH值)
echo ${PATH}
在变量前加$和${变量}的方式式都可以使用。
- 当需要修改某个变量的内容时,只需使用等号(=)连接变量和它的内容就好。
当使用echo ${myname},而myname尚未被设置时,无返回值,只需使用myname=root,再使用echo ${myname},就会返回root。
因此,当一个变量尚未被设置时,默认的内容为空。
变量在被设置时,需要符合以下规定: - 变量设置规则:
- 变量与变量内容以一个等号【=】来连接。
- 等号两边不能直接接空格。
- 变量名只能是英文字母或数字,开头字符不能是数字。
- 变量内容若有空格可使用双引号【"】或者【'】将变量内容结合起来。
- 双引号内的特殊字符如$等,可以保有原本的特性。
- 单引号内的特殊字符则仅为一般字符(纯文本)
- 可使用转义字符转换为一般字符。
- 在一串命令中,如果需要借由其他命令提供信息时,可以使用反单引号【
命令】或【$(命令)】。、 - 若该变量为增扩变量内容时,则可以使用
"$变量名称"或${}累加内容。 - 若变量需要在其他子程序执行时,则需要以export来使变量变成环境变量。
- 通常大写字符为系统默认变量,自行设置变量可以使用小写字符,方便判断。
- 取消使用变量的方法为使用unset:【unset 变量名称】
- 子进程:在当前已使用的shell下,去启用一个新的shell,新的shell就是子进程。
- 一般情况下,父进程的自定义变量无法在子进程中使用,但是可以通过export将变量声明为环境变量,就可以在子进程中使用。
在变量设置中,单引号和双引号是不同的,双引号任然可以保有变量的内容,单引号只能是一般字符(字母或数字),不能是特殊符号。- 假设定义变量
name=Xuan,使用echo $name就可以返还Xuan。 - 在
myname="$name its me"情况下,echo $myname为Xuan its me。 - 在
myname='$name its me'情况下,echo $myname为$name its me。
在命令执行过程中,反单引号( ` )代表着:在反单引号内的命令会优先被执行,其执行出的结果将被作为外部的输入信息。
- 假设定义变量
2.3 环境变量的功能
环境变量可以实现许多功能,包括根目录的变换,提示字符的显示,执行文件查找的路径等。
如果需要查询在当前shell环境中默认的环境变量,可以使用env和export。
-
使用
env观察环境变量和常见环境变量
直接使用env:env
会列出目前的shell环境下所有的环境变量与其内容。
env就是environment(环境)的简写,直接使用就是列出所有的环境变量,直接使用export也是一样的内容。
以下介绍一些常见的环境变量:
-
HOME
代表用户的根目录。当使用cd ~回到自己的根目录时,就是使用的这个变量。 -
SHELL
代表目前这个环境使用的SHELL是哪个程序。Linux默认使用/bin/bash。 -
HISTSIZE
与历史命令有关,所有执行过的命令都可以被系统记录下来,这个值代表记录的条数。 -
MAIL
使用mail这个命令收信时,系统会去读取的邮箱文件。 -
PATH
就是执行文件查找的路径,目录与目录中间以冒号(:)分隔开,由于文件的查找是依序有PATH的变量内的目录来查询的,所以,目录的顺序也是很重要的。 -
LANG
就是语系数据,非常重要。 -
RANDOM
就是随机数的变量。这个变量的内容介于0~32767,只需echo $RANDOM,系统就会随机取出一个介于0~32767的数值。
如果想要使用0~9或者其他的内容,可以利用declare生命数据类型:declare -i number=RANDOM*10/32768;echo number
此时就会随机刷新出0~9之间的数值。
- 使用
set观察所有变量(含环境变量和自定义变量)
set除了环境变量之外,还会将其他在bash内的变量通通显示出来。
一般来说,不论是否为环境变量,只要是和我们目前这个shell的操作界面有关的变量,通常都会被设置为大写字符。
基本上,在Linux默认的情况中,使用{大写的字母}来设置的变量一般为系统内需要的变量。
以下介绍一些重要的环境变量: - PS1:(提示字符的设置)
这就是我们的命令提示符。当我们按下[Enter]按键去执行某个命令后,最后要再次出现提示字符时就会主动去读取这个变量值。
PS1演示:[root@user1 ~]
这个值是可以修改的。
一下是一些符号的意义:- \d:可显示出【星期 月 日】的日期格式,如【Mon Fed 2】
- \H:完整的主机名。
- \h:仅取主机名在第一个小数点之前的名字。
- \t:显示时间,为24小时格式的【HH:MM:SS】;
- \T:显示时间,为12小时格式的【HH:MM:SS】;
- \A:显示时间,为24小时格式的【HH:MM】;
- \@:显示时间,为12小时格式的【am/pm】样式;
- \u:目前用户的账号名称;
- \v:BASH的版本信息;
- \w:完整的工作目录名称,由根目录写起的目录名称,但根目录会以~替换;
- \W:利用basename函数取得工作目录名称,所以仅会列出最后一个目录名;
- \#:执行的第几个命令;
- \:提示字符,如果是root时,提示字符为#,否则就是 ;
如果想设置PS1,只需PS1='[...格式...]'就可以轻松定义自己的命令提示符。 - $:(关于本shell的PID)
美元符号本身也是个变量。这个东西代表的是目前这个shell的进程号,就是所谓的PID。 - ?:(关于上个执行命令的返回值)
这个命令是上一个执行的命令所返回的值。
当我们执行某些命令时,这些命令都会返回一个执行后的代码。一般来说,如果成功的执行该命令,则会返回一个0值。
使用echo $?,上一条命令执行成功时,返回值为0,执行失败时,返回返回错误代码。
- OSTYPE,HOSTTYPE,MACHTYPE
OSTYPE:操作系统的类型。 - export:自定义变量转成环境变量
前面提到过,env观察环境变量,set观察所有变量(含环境变量与自定义变量)。
这两者差异在于该变量是否会被子进程所继续引用 。
当我们登陆Linux并取得一个bush之后,这个bush就是一个独立的进程,这个进程的识别所使用的就是进程标识符,也就是PID。
接下来在这个bash下所执行的任何命令都是由这个bash所衍生来的,这些被执行命令就被称为子进程。
而在子进程中,会继承父进程的环境变量,子进程不会继承父进程的自定义变量。
如果想要在子进程中使用,就需要使用export命令将自定义变量变成环境变量。
因此,我们只需在主文件中使用export声明好需要的自定义变量,就可以把自己的变量设置共享给后来调用的文件或其他进程。
2.4 影响显示结果的语系变量
使用locale -a命令,就可以查询出我们的linux支持的语系。
而直接使用localte,会显示出与语系有关的变量。
如果其他的语系变量都未设置,且前面提到的LANG设置过,那么其他的语系变量都会被这个变量所替换。
每个用户都可以根据自己的喜好去调整语系,整体系统默认的语系定义在/etc/locale.conf里面。
2.5 变量的有效范围
在运行程序的时候,如果出现父进程和子进程的不同进程关系时,则变量是否可以被引用与export有关,被export变量,我们可以称它为环境变量。
环境变量可以被子进程引用,而其他的自定义变量内容就不会存在与子进程中。
因为内存配置的关系,环境变量的数据可以被子进程引用:
* 当启动一个shell时,操作系统会分配一内存区域给shell使用,此内存中的变量可以让子进程使用。
* 如果在父进程利用export功能,可以让自定义变量的内容写到上述的内存区域中(环境变量)。
* 当加载进另一个shell(即启动子进程,而离开原本的父进程),子shell可以将父shell的环境变量所在的内存区域导入到自己的环境变量区块当中。
通过export这样的功能,我们就可以让某些变量在相关的进程中存在,来帮助我们更方便的操作环境。
2.6 变量键盘读取,数组与声明:read,array,declare
以上提到的变量设置功能,都是由命令行直接设置的。
而在bash中,也可以让用户能够经由键盘输入,此外还可以定义这个变量的属性。
- read
read用于读取来自键盘输入的变量,通常用于shell脚本的编写。- 用法演示:
bash
read [-pt] variable
-
- -p:后面可以接提示字符。
- -t:后面可以接等待的【秒数】。
- 如果不加任何参数,直接加上变量名称,下面会出现一个空白行等待输入。
- -p:后面可以接提示字符。
-
declare,typeset
declare或typeset是一样的功能,就是声明变量的类型。- 如果
declare后面不接任何参数,就会像set一样,bash会主动把所有的变量名称与内容全部显示。
bash
declare [-aixr] variable
-
- -a:将后面名为variable的变量定义成为数组(array)类型。
- -i:将后面名为variable的变量定义成为整数(integer)类型。
- -x:用法与export一样,就是将后面的variable变成环境变量。
- -r:将变量设置成为readonly类型,该变量不可被更改内容,也不能被unset。
默认情况下,bash对变量有一些定义: - 变量类型默认为字符串,所以若不指定变量类型,则1+2为一个字符串而不是计算式。
- bash环境中的数值运算,默认最多仅能达到整数形态。
- -a:将后面名为variable的变量定义成为数组(array)类型。
- 数组(array)变量类型
某些时候,必须以数组来声明一些变量:
bash
var[index]=content
读取时,需要以${数组}的形式读取。
2.7 与文件系统及程序的限制关系:nlimit
为防止多个用户同时访问文件导致linux主机内存超载,bash会显示用户的某些系统资源,包括可以开启的文件数量,可以使用的cpu时间,可以使用的内存总量等。
bash
ulimit [-SHacdfltu] [配额]
- -H:hard limit,严格的设置,必定不能超过这个设置的数值。
- -S:soft limit,警告的设置,可以超过这个设置值,但是如果超过则有警告信息。
通常,soft会比hard小,若soft设为80,hard设置为100,当使用90时,系统会有警告信息。 - -a:后面面不接任何选项和参数,可列出所有的限制额度。
- -c:当某些程序发生错误时,系统可能会将该程序在内存中的信息写成文件(除错用),这种文件就被称为内核文件(core file)。此为限制每个内核文件的最大容量。
- -f:此shell可以建立的最大文件容量,单位为Kbytes。
- -d:程序可使用的最大段内存容量。
- -l:可用于锁定(lock)的内存量。
- -t:可使用的最大CPU时间(单位为秒)。
- -u:单一使用者可以使用的最大进程(process)数量。
单一文件系统能够支持的单一文件大小与block的大小有关,但是文件系统的限制容量都允许的太大了。
如果想要让用户建立的文件不能太大,就可以使用limit -f来限制用户可以建立的文件的大小。
2.8 变量内容的删除,取代与替换(可选)
变量除了可以直接设置来修改原本的内容之外,也可以通过简单的操作来将变量的内容进行微调。
- 变量内容的删除与替换
变量内容可以很简单的通过几个东西来进行删除。
假设有一个变量str={hello_world_hello}。
删除操作
- #:从变量开头删除匹配的最短内容;
bash
echo ${str#*_}
此处表示从变量开头删除最短匹配*_的部分 ,即hello_。
输出结果为world_hello。
- ##:从变量开头删除匹配的最长内容;
bash
echo ${str##*_}
此处表示从变量开头删除最长匹配*_的部分 ,即hello_world_。
输出结果为hello。
- %:从变量结尾删除匹配的最短内容;
bash
echo ${str%*_}
此处表示从变量末尾删除最短匹配*_的部分 ,即_hello。
输出结果为hello_world。
- %%:从变量结尾删除匹配的最长内容;
bash
echo ${str%%*_}
此处表示从变量末尾删除最长匹配*_的部分 ,即_world_hello。
输出结果为hello。
替换操作
- /:替换第一个匹配内容;
bash
echo ${str/_/-}
此处表示替换变量中第一个_,替换为-。
- //:替换所有的匹配内容;
bash
echo ${str//_/-}
此处表示替换变量中所有的_,替换为-。
总结
| 变量设置方式 | 说明 |
|---|---|
| ${变量#关键词} | 若变量内容从头开始的数据符合【关键字】,则将符合的最短数据删除 |
| ${变量##关键词} | 若变量内容从头开始的数据符合【关键字】,则将符合的最长数据删除 |
| ${变量%关键字} | 若变量内容从末尾向前的数据符合【关键字】,则将符合的最短数据删除 |
| ${变量%%关键字} | 若变量内容从末尾向前的数据符合【关键字】,则将符合的最长数据删除 |
| ${变量/旧字符串/新字符串} | 若变量内容符合【旧字符串】则【第一个旧字符串会被新字符串替换】 |
| ${变量//旧字符串/新字符串} | 若变量内容符合【旧字符串】则【全部的旧字符串会被新字符串替换】 |
-
某些时刻,我们需要提前【判断】某个变量存在,若变量存在则使用既有的设置,若变量不存在则给予一个常用的设置。
可以这样设置:new_var = ${old_var-content}
-
new_var:新的变量,主要用来替换旧变量,新旧变量名称常常是一样的。 -
content:关键字部分,必须存在。 -
old_var:旧的变量,被测试的项目。 -
{old_var-content}:变量的内容,这个部分是在【给予未设置变量的内容】。 -
var和str为变量,针对str是否有设置来决定var的值。以
str:代表【str没设置或为空的字符串时】,至于str则仅为【没有该变量】。
| 变量设置方式 | str没有设置 | str为空字符串 | str已设置非为空字符串 |
|---|---|---|---|
| var=${str-expr} | var=expr | var= | var=$str |
| var=${str:-expr} | var=expr | var=expr | var=$str |
| var=${str+expr} | var= | var=expr | var=expr |
| var=${str:+expr} | var= | var= | var=expr |
| var=${str=expr} | str=expr var=expr | str不变 var= | str不变 var=$str |
| var=${str:=expr} | str=expr var =expr | str=expr var=expr | str不变 var=$str |
| var=${str?expr} | expr输出至stderr | var= | var=$str |
| var=${str:?expr} | expr输出至stderr | expr输出至stderr | var=$str |
3.命令别名与历史命令
3.1 命令别名设置:alias,unalias
当某个常用命令很长的时候,命令别名是一个很有用的东西,通常使用alias来命名。
alias 别名='命令 选项...'
-
直接使用
alias,会显示出目前所有的命令别名。
当想要取消命令别名时,可以使用unalias。unalias 命令别名
3.2 历史命令:history
使用history可以查询我们曾经执行过的命令。
history [n]
history [-c]
history [-raw] histfiles
-
n:数字,意思是【要列出最近的n条命令行表】的意思。
-
-c:将目前的shell中的所有history内容全部清除。
-
-a:将目前新增的history命令新增入histfiles中,若没有加histfiles,则默认写入~./bash history。
-
-r:将histiles的内容读到目前这个shell的history记录中。
-
-w:将目前的history记录内容写入histfiles中。
正常情况下,历史命令的读取与记录是这样的: -
当我们以bash登陆Linux主机之后,系统会主动地由家目录的
~/.bash_history读取以前曾经执行过的命令,~/.bash_history记录的数据量和bash中HISTFLESIZE的设置值有关。 -
当我们登陆主机,执行命令后,注销时,系统就会将最近的HISTFILESIZE条历史命令更新到记录文件中。
-
也可以使用
history -w命令强制立刻写入,而~/.bash_history记录的条数是固定的,由参数HISTFILESIZE决定,每有新的信息写入,旧的信息就会被删除。
此外还有其他用法:! [number] (执行第number条命令)
! [command] (执行以command为开头的命令)
!! (执行上一个命令) -
同一账号同时多次登陆的history写入问题
当我们在一个账号中同时打开多个bash页面执行命令时,每个bash都会有自己的历史命令记录,直到注销时才会更新记录文件,每注销一个bash,对应bash的记录就会被写入记录文件,而后面注销的bash的记录信息可能会覆盖前面的记录。 -
无法记录时间
历史命令是按顺序记录的,无法记录命令执行的时间。
4.Bash shell 的操作环境
4.1 路径与命令查找顺序
由前面可知,系统中其实有不少的同名命令,当一个命令被执行时,是有一定的查找顺序的:
- 1.以相对/绝对路径执行命令。
- 2.由alias找到该命令来执行。
- 3.由bash内置的命令来执行。
- 4.通过$PATH这个变量的顺序查找到的第一个命令来执行。
4.2 bash的登陆与欢迎信息:/etc/issue,/etc/motd
bash也有登陆画面与欢迎信息,都记录在/etc/issue里面。和$PS1这变量一样,issue文件中的内容也是可以使用反斜杠作为变量使用。
issue内的各代码意义:
| 代码名 | 意义 |
|---|---|
| \d | 本地端时间的日期 |
| \l | 显示第几个终端页面 |
| \m | 显示硬件的的等级 |
| \n | 显示主机的网络名称 |
| \O | 显示domain name |
| \r | 操作系统的版本(相当于uname -r) |
| \t | 显示本地端时间的时间 |
| \S | 操作系统的名称 |
| \v | 操作系统的版本 |
- 除
/etc/issue之外,还有一个/etc/issue.net,这是提供给telnet这个远程登陆程序使用的,当使用telnet连接到主机时,主机的登陆画面就会显示/etc/issue.net。当想要用户登陆后获得一些信息,就可以把信息加到/etc/motd中。
4.3 bash的环境配置文件
在Linux中本身就有一些配置文件存在,让bash在启动时直接读取这些文件,以规划好bash的操作系统。而这些配置文件又可以分为全局系统配置文件已经用户个人偏好配置文件。
前面的提到的命令别名,自定义的变量,在注销bash后就会失效,如果想要保留设置,就需要写入到配置文件中。
- login 与 non-login shell
在开始介绍bash的配置文件前,首先要了解login shell和non-login shell,重点在于有没有登陆(login)。- login shell:指用户登陆系统时启动的第一个shell。
例如:- 在图形化界面登陆Linux,系统会分配一个login shell。
- 通过
ssh登陆远处主机时,启动的也是login shell。 - 手动使用
bash --login,也可以强制启动一个login shell。
- non-login shell:取得bash的方法不需要重复登陆的操作。
例如:- 已经登陆了图形界面,再打开一个终端,里面的shell就是non-login shell。
- 在shell中输入bash启动的shell,也是non-login shell。
- login shell:指用户登陆系统时启动的第一个shell。
在这两个取得bash的情况中,读取的配置文件不同。
login shell只会读取这两个配置文件:
-
/etc/profile:这是系统整体的设置,最好不要修改这个文件。 -
~/.bash_profile或~./bash_login或~/.profile:属于用户个人设置,要添加自己的数据时,就需要写入到这里。
-
etc/profile(login shell才会读)这个配置文件可以利用用户标识符(UID)来决定很多重要的变量数据,这也是每个用户登陆取得bash时一定会读取的配置文件。当需要帮助所有用户设置整体环境时,就是要改这个文件。主要变量有:
- PATH:会根据UID决定PATH变量要不要含有
sbin的系统命令目录。 - MAIL:会根据账号设置好的用户
mailbox到/var/spool/mail账号名。 - USER:根据用户的账号设置此变量内容。
- HOSTNAME:根据主机的hostname命令决定此变量内容。
- HISTSIZE:历史命令记录条数,CentOS 7.x设置为1000。
- umask:包括root默认为022而一般用户为002等。
/etc/profile还会调用外部的配置文件,在CentOS 7.x默认的情况下,下面的文件会被依次调用:
- PATH:会根据UID决定PATH变量要不要含有
-
/etc/profile.d/*.sh这代表这个目录内的众多文件。只要在
/etc/profile.d/这个目录内且扩展名为.sh,另外,用户能够具有r的权限,那么该文件就会被/etc/profile调用。在CentOS 7.x中,这个目录下面的文件规范了bash操作界面的颜色、语系、ll与ls命令的命令别名、which的命令别名等。如果你需要帮所有用户设置一些共享的命令别名时,可以在这个目录下面自行建立拓展名为.sh的文件,并将所需要的数据写入即可。 -
/etc/locale.conf这个文件是由
/etc/profile.d/lang.sh调用的,这也是决定bash默认使用何种语系的重要配置文件。文件里最重要的就是LANG/LC_ALL这些个变量的设置,在前面的locale讨论过。 -
/usr/share/bash-completion/completions/*
[TAB]命令除了命令补齐,文件名补齐之外,还可以进行命令的选项/参数补齐功能,这就是从这个目录里面找到相对应的命令来处理,而这个目录下的内容是由/etc/profile.d/bash_completion.sh这个文件加载的。总之,
bash的login shell情况下所读取整体环境配置文件其实只有/etc/profile,但是/etc/profile还会调用出其他的配置文件。 -
~/.bash_profile(login shell才会读)bash在读完了整体环境设置的
/etc/profile/并借此调用其他配置文件后接下来就会读取用户的个人配置文件。在 login shell 的 bash 环境中,所读取的个人偏好配置文件其实主要有三个,依序分别为:-
~./bash_profile -
~./bash_login -
~./profile其实 bash 的 login shell 设置只会读取上面三个文件的一个,而读取的顺序则是依照上面的顺序。也就是说,如果
~/.bash_profile存在,那么其他两个文件无论有无存在,都不会被读取,如果第一个文件不存在,才会去读取第二个文件,而第二个文件也不存在时,才会读取第三个文件。以下是
~/.bash_profile文件的内容

其中前三行在判断并读取 ~/.bashrc
-
bash
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
后两行在修改环境变量
bash
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
意思是把用户自己的的 ~/bin 和 ~/.local/bin 目录加入到原来的环境变量 PATH 中,这样用户就可以把自己的可执行文件(脚本之类)放在家目录的 ~/bin 下,这样就可以在命令行直接输入可执行文件的名字来运行,不需要写出完整路径。
-
source :读入环境配置文件的命令。
etc/profile 与 ~/.bash_profile 都是在取得 login shell 后才会读取的配置文件,所有当我们将自己的偏好设置写入上述文件时,通常需要先注销再登录才能使设置生效。
而使用 source 或小数点 (.) 就可以直接读取配置文件而不注销登录。
比如一个常见的情况,当修改了
~/.bashrc,就可以使用source ~/.bashrc或者~/.bashrc将刚刚设置的内目前读入目前环境中。 -
~/.bashrc (non-login shell会读)
当取得 non-login shell时,该 bash的配置文件仅会读取 ~/.bashrc 。
Centos会主动的调取 /etc/bashrc 文件,它会帮 bash 定义下面的内容:
根据不同的UID设置umask的值;
根据不同的UID设置提示字符(就是PS1变量);
调用 /etc/profile.d/*.sh 的设置;
而这个 /etc/bashrc 是CentOS特有的(或者说是Red Hat系统特有的),其他linux发行版可能会使用不同的文件名。
而 ~/.bashrc 会调用 /etc/bashrc 及 /etc/profile.d/*.sh ,因此没有 ~/.bashrc 文件不存在,那么 bash 的提示字符可能就会出现异常。
-
其他相关配置文件
还有一些其他配置文件也会影响。
/etc/man_db.conf
这个文件的内容规范了使用 man 的时候, man page 的路径到哪里去寻找。
需要修改这个文件的情况是:当以 tarball 的方式来安装软件时, man page 可能会放置在 /usr/local/软件名/man 里面,这时就需要以手动方式将该路径加到 /etc/man_db.conf 里面,否则使用 man 时会找不到相关的说明文件。
~/.bash_history
默认情况下,历史命令就记录在这里,而这个文件能够记录几条数据,则与 HISTFILESIZE 这个变量有关。每次登陆 bash 后, bash 会先读取这个文件,将所有的历史命令存入内存。
~/.bash_logout
记录了【当我注销bash之后,系统再帮我做完什么操作后才离开】的意思。默认情况下,注销时, bash 只是清理掉屏幕的信息,不过也可以将一些备份或者比较重要的任务卸载这个文件中(比如清空缓存),当离开linux时,就会自动执行。
4.4终端的环境设置:stty、set
在首次登录Linux时,可以在 tty1~tty6 这个六个命令行模式的终端环境中登录,在登录时可以取得一些字符设置的功能。比如可以利用退格键(backspace),来删除命令行上的字符,也可以使用 [ctrl]+c 来强制终止一个命令的运行,当输入错误时,就会有声音警告。这是因为在登录终端时会自动获取一些终端的输入环境的设置。
目前我们使用的linux发行版帮我们设置好了最棒的用户环境 ,不过在某些UNIX-like的机器中,还是需要动手修改才能让输入更加方便。
使用 stty (setting tty终端的意思), stty 也可以帮助设置终端的输入按键代表的意义。
bash
stty [-a]
-
-a:将所有的stty参数列出来。命令结果如图:

其中
^表示为[ctrl]按键,其中一些关键词的含义为: -
intr:发送一个interrupt的信号给目前正在run的程序。 -
quit:发送一个quit的信号给目前正在run的程序。 -
erase:向后删除字符。 -
kill:删除在目前命令行上的所有文字。 -
eof:End of file的意思,代表【结束输入】。 -
start:在某个程序停止后,重新启动它的output。 -
stop:停止目前屏幕的输出。 -
susp:送出一个terminal stop的信号给正在运行的程序。除
stty外,bash还有一些自己的终端设置值,是利用set来设置的,set不仅可以显示一些变量,还可以设置整个命令输入输出的环境。
bash
set [-uvCHhmBx]
选项与参数:
-
-u:默认不启用,若启用后,当未设置变量时,会显示错误的信息、 -
-v:默认不启用,若启用后,在信息被输出前,会先显示信息的原始内容。 -
-x:默认不启用,若启用后,在命令被执行前,会显示命令内容(前面有++符号)。 -
-h:默认启用,与历史命令有关。 -
-H:默认启用,与历史命令有关。 -
-m:默认启用,与任务管理有关。 -
-B:默认启用,与中括号[]的作用有关。 -
-C:默认不启用,若使用>等,则若文件存在时,该文件不会被覆盖。
还有一些其他的按键设置功能,就是在/etc/inputrc这个文件中设置的。
还有/etc/DIR_COLORS*与/usr/share/terminfo/*等,也都是与终端有关的环境配置文件。
以下为bash默认的组合键:组合按键 执行结果 Ctrl + C终止目前的命令 Ctrl + D输入结束(EOF),例如邮件结束时 Ctrl + M即回车 Ctrl + S暂停屏幕的输出 Ctrl + Q恢复屏幕的输出 Ctrl + U在提示字符下,将整列命令删除 Ctrl + Z暂停目前的命令
4.5 通配符与特殊符号
在bash操作中还有一个处理数据十分方便的功能,通配符 。
以下为常用的通配符:
| 符号 | 意义 |
|---|---|
* |
代表【0个到无穷多个】任意字符 |
? |
代表【一定有一个】任意字符 |
[] |
同样表示【一定有一个在括号内】的字符(非任意字符)。例如[abcd]表示【一定有一个字符,可能是a、b、c、d这四个任何一个】 |
[-] |
若有减号在中括号内时,代表【在编码顺序内的所有字符】。例如[0-9]表示0和9之间的所有数字,因为数字的语系编码是连续的 |
[^] |
若中括号内的第一个字符为指数字符^,那就表示【反向选择】,例如[^abc]代表一定有一个字符,只要是非a、b、c的其他字符就接受的意思。 |
除了通配符之外,bash环境中还有一些特殊符号:
| 符号 | 内容 |
|---|---|
# |
注释符号,常常被使用在脚本中,视为说明,在后的数据均不执行 |
\ |
转义符,将【特殊字符或者通配符】还原成一般字符 |
| ` | ` |
; |
连续命令执行分隔符,连续行命令的界定 |
~ |
用户的家目录 |
$ |
使用变量前导符,亦即是变量之前需要加的变量替换值 |
& |
任务管理,将命令变成后台命令 |
! |
逻辑运算意义上的【非】not的意思 |
/ |
目录符号,路径分隔的符号 |
>,>> |
数据流重定向,输出定向,分别是【替换】与【累加】 |
<,<< |
数据流重定向,输入定向 |
' ' |
单引号,不具有变量替换的功能 |
" " |
双引号,具有变量替换的功能 |
| `` | 两个【`】中间为可以先执行的命令,亦可以使用$() |
() |
在中间为子shell的起始与结束 |
{} |
在中间为命令区块的组合 |
5.数据流重定向
数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据传输到其他的地方。
5.1 什么是数据流重定向
数据流重定向要从命令的执行结果谈起。
当要执行一个命令时,它的流程是这样的:

当执行一个命令时,这个命令可能先从文件读入数据,经过处理之后,再将数据输出到屏幕上。
上图中standard output与standard error output分别代表【标准输出(STDOUT)】与【标准错误输出(STDERR)】,这两个默认都是输出到屏幕上的。
standard output与standard error output
标准输出指的是命令执行所返回的正确信息,而标准错误执行指的是命令执行失败后,所返回的错误信息。
举例来说,假设系统中有/etc/txt1,但是没有/etc/txt2,而此时执行【cat /etc/txt1 /etc/txt2】这个命令时,cat会进行:- 标准输入(stdin):代码为0,使用< 或<< 。
- 标准输出(stdout):代码为1,使用>或>> 。
- 标准错误输出(stderr) :代码为2,使用2> 或2>> 。
当使用ll /时:
屏幕中会显示根目录(/)下文件夹的信息。
而使用ll / > ~/rootfile,此时屏幕上不会显示任何信息。
使用ll ~/rootfile,即可发现rootfile文件被建立了。
再使用cat ~/rootfile就可以查看到原本应该在屏幕上显示的数据,那么再使用ll /home > ~/rootfile后,rootfile文件中就只有ll /home的数据了,原本的数据被替换了,这是因为该文件的建立方式是: - 该文件如果不存在,系统会自动建立。
- 当这个文件存在时,系统会将这个文件的内容全部清空,然后再将数据写入。
- 若以>输出到一个已存在的文件中,这个文件就会被覆盖。
如果想要将数据累加而不是替换,那么使用两个大于的符号就行了,即ll / >> ~/rootfile。
标准错误输出也是相同,通过2>(覆盖)和2>>(累加)的形式进行数据重定向。
stdout的代码是1,stderr代码是2,也就是说: - 1> :以覆盖的方法将【正确的数据】输出到指定的文件或者设备上。
- 1>> :以累加的方法将【正确的数据】输出到指定的文件或者设备上。
- 2> :以覆盖的方法将【错误的数据】输出到指定的文件或者设备上。
- 2>>:以累加的方法将【错误的数据】输出到指定的文件或者设备上。
举一个使用场景,以一般用户的身份执行find命令时,会因为权限问题出现报错,假如使用find /home -name .bashrc查询/home目录下是否有.bashrc文件存在,而在/home目录下又有其他账号存在,那么没有权限进入这些文件就必然会报错,也会产生正确数据。
使用find /home -name .bashrc > list只能将正确输出数据存储在list中,错误输出数据依然会显示。想要将正确输出信息和错误输出信息就需要find /home -name .bashrc >list_right 2>list_error,错误输出存储在list_error,正确信息存储在list_rught中。 /dev/null垃圾桶黑洞设备与特殊写法
如果知道会产生错误信息,所有想要忽视掉错误信息就可以使用/dev/null。
比如find /home -name .bashrc 2> /dev/null,这样就可以丢弃掉错误数据,只显示正确输出数据。
而当想要将正确和错误输出信息存储在一个文件夹中时,就需要特殊的写法:
bash
find /home -name .bashrc > list 2> list <==错误
find /home -name .bashrc > list 2>&1 <==正确
find /home -name .bashrc &> list <==正确
第一个命令错误的原因是,两股数据同时写入一个文件,有没有使用特殊的语法,此时两股数据可能会交叉写入该文件内,造成次序的错乱。写入同一个文件的写法既可以使用2>&1,也可以使用&>。
standard input : < 与 <<
<,即stdin,就是【将原本需要有键盘输入的数据,改由文件内容来替换】。
在此举例:
使用cat > catfile,将会创建一个catfile文件,此时在键盘上输入this is a file,按下[Ctrl]+d退出,就会得到一个内容为this is a file的文件catfile。
这个输入this is a file的过程就可以使用<来代替:cat > catfile < ~/.bashrc
这个命令就是将~/.bashrc文件中的内容全部出入到catfile文件中,以>代替了手动输入的过程。如果使用ll命令就可以发现,这两个文件的大小一模一样。
<<,代表【结束的输入字符】。
在此举例:
cat > catfile << "eof",当在键盘上输入数据时,输入关键词eof就可以结束输入。
5.2 命令执行的判断依据:;、&&、||
; (不考虑命令相关性的连续命令执行)
某些情况下,需要一次执行多个命令。例如,想要在关机前先执行两次sync同步写入磁盘后再shutdown计算机,就可以sync; sync; shutdown -h now。
在命令与命令间利用分号(;)隔开,分号前面的命令执行完就会执行后面的命令。
而假如想要在某个目录下建立一个文件,如果目录存在就建立文件,不存在就算了,下一个命令再对这个文件进行操作。
$?(命令返回值)与&&或||
当两个命令之间有依赖性,而这个依赖性主要判断的地方在于前一个命令执行结果是否正确,此时就可以使用&&或||。还有一个命令返回值,【若前一个命令执行的结果为正确,在linux下面会返回一个$?=0的值】。可以通过这个返回值来判断后续的命令是否执行。
| 命令执行情况 | 说明· |
|---|---|
| cmd1 && cmd2 | 1. 若 cmd1 执行完毕且正确执行(?=0),则开始执行cmd2 2.若cmd1执行完毕且为错误(?=0),则cmd2不执行 |
| cmd1 || cmd2 | 1. 若 cmd1 执行完毕且正确执行(?=0),则cmd2不执行 2.若cmd1执行完毕且为错误(?=0),则开始执行cmd2 |
- cmd1 执行成功,再执行cmd2
cmd1 && cmd2 - cmd1 执行失败,再执行cmd2
cmd1 || cmd2 - 无论cmd1是否执行成功,都执行cmd2
假如不知道/tmp/abc文件夹是否存在,但是就是要创建/tmp/abc/file文件:
ls /tmp/abc || mkdir /tmp/abc && /tmp/abc/file- 若
/tmp/abc不存在,则ls /tmp/abc返回$?≠0,在||下就会执行mkdir /tmp/abc,这个命令会成功执行并但会$?=0,在&&下就会执行/tmp/abc/file,最终成功创建。 - 若
/tmp/abc存在,则ls /tmp/abc返回$?=0,在||下不会执行mkdir /tmp/abc,$?=0继续向后传,在&&下就会执行/tmp/abc/file,最终成功创建。
由于命令时一个一个执行的,因此如果使用判断,&&和||的顺序就不能变,一般就是:
cmd1 && cmd2 || cmd3
- 若
6. 管道命令(pipe)
bash命令执行时有时会有输出的数据出现,这些数据可能必须经过几道处理之后才能得到需要的格式,这时就牵扯到管道命令的问题。管道命令使用的是【|】这个界定符号。
假如想要知道/etc下有多少文件,可以使用ls /etc来查看,但是数据过多,此时就可以使用管道符加less。
ls -al /etc | less,相当于将ls输出的数据以less的形式查看。
其实这个管道命令【 | 】只能处理经由前面一个命令传来的正确信息,也就是标准输出的信息,对于标准错误并没有直接处理的能力。

在每个管道后面接的第一个数据必定是【命令】,而且这个命令必须要能接受标准输入的数据,这样的命令才是管道命令。
比如less、more、head、tail这种,可以接受标准输入的数据就是管道命令。
ls、cp、mv这种不会接收来着stain的数据的就不是管道命令。
也就是说:
- 管道命令仅会处理标准输出,对于标准错误会予以忽略。
- 管道命令必须能够接受来自前一个命令的数据成为标准输入继续处理才行。
6.1 选取命令:cat、grep
选取命令就是将一段数据经过分析之后,取出我们想要的,或是经由分析关键词,取得我们想要的那一行,一般来说,选取信息通常是针对【一行一行】来分析,而不是整篇分析。
cut
这个命令可以将一段信息的某一段【切】出来,处理的信息以【行】为单位。
bash
cut -d'分隔字符' -f fields
cut -c 字符区间
选项与参数:
-d:后面接分隔字符,与-f一起使用。-f:根据-d的分隔字符将一段信息划分为数段,用-f取出第几段的意思。-c:以字符的单位取出固定字符区间。
举例来说:
echo ${PATH} | cut -d ':' -f 5,就是将echo ${PATH}以【:】分隔去除第五段,将-f后换成3,5就是去第三段和第五段。
cut主要用途在于将同一行里面的数据进行分解,最常使用在分析一些数据或文字数据的时候。
grep
grep是分析一行信息,若当中有需要的信息,就将改行单独拿出。
bash
grep [-acinv] [--color=auto] '查找字符' filename
选项与参数:
-a:将二进制文件以文本文档的方式查找数据。-c:计算找到'查找字符'的次数。-i:忽略大小写的不同,将大小写视为相同。-n:顺便输出行号。-v:反向选择,亦即显示出没有'查找字符'内容的那一行。--color=auto:可以将找到的关键字部分进行颜色显示。
6.2 排序命令:sort、wc、uniq
很多时候,我们回去计算一次数据里面的相同形式的数据总数,此时就需要排序与计算之类的命令。
sort
sort是一个排序命令,还可以根据不同的数据形式进行排序,例如数字与文字的排序就不一样。
bash
sort [-fbMnrtuk] [file or stdin]
-f:忽略大小写的差异,例如将A与a视为编码相同。-b:忽视最前面的空格字符部分。-M:以月份的名字来排序。-n:使用【纯数字】进行排序(默认是以文字形式排序)-r:反向排序。-u:就是uniq,相同的数据中,仅出现一行代表。-t:分隔符号,默认用[Tab]键来分隔。-k:以哪个区间来进行排序的意思。
uniq
假如排序完成后,想要将重复的数据仅列出一个显示,就可以使用这个命令,这个命令只能处理相邻的重复行,通常与sort一起使用。
bash
uniq [-ic]
-i:忽略大小写字符的不同。-c:进行计数。
wc
wc命令用于计算文件内容。
bash
wc [-lwm]
-l:仅列出行。-w:仅列出多少字(英文字母)。-m:多少字符。
使用wc命令,会返回三个数字,分别代表:行,字数,字符数。
6.3 双向重定向
">",标准输出会将数据流整个传送给文件或者设备,因此除非去读取该文件或设备,否则就无利用到这个数据流,假如我们想要在这个数据流的处理过程中将某段信息存储下来,就可以使用tee。
tee会同时将数据流分送到文件与屏幕,而输出到屏幕的就是stdout的内容。
bash
tee [-a] file
-a:以累加方式,将数据加入到file中。
tee可以将standard output转存一份文件内并将同样的数据继续送到屏幕去处理,这样除了可以让我们同时分析一份数据并记录下来之外,还可以作为处理一份数据的中间缓存记录。
6.4 字符转换命令:tr、col、join、paste、expand
以下是一些字符转换命令在管道当中的使用方法:
tr
tr可以用来删除一段信息当中的文字,或是进行文字信息的替换。
bash
tr [-ds] SET1 ...
-d:删除信息当中的SET1这个字符。-s:替换掉重复的字符。
比如cat file | tr '[a-z]' '[A-Z]',就是将cat输出内容中的a-z全部替换为A-Z。并且此命令单引号可写可不写。
col
col大多数的用途都是简单地处理将[tab]转化为空格键
bash
col [-xb]
-x:将tab键转换为对等的空格键。
join
join命令是在处理两个文件之间的数据,主要是在处理【两个文件当中,有相同数据的那一行,才能将它加在一起】。
bash
join [-til2] file1 file2
-t:join默认以空格字符分隔数据,并且比对【第一个栏位】的数据,如果两个文件相同,则将两条数据连成一行,且第一个栏位放在第一个。-i:忽略大小写的差异。-1:这个是数字的1,代表【第一个文件要用哪个栏位来分析】的意思。-2:代表【第二个文件要用哪个栏位来分析的意思】。
paste
paste命令时直接将两行贴在一起,且中间以[tab]键隔开。
bash
paste [-d] file1 file2
-d:后面可以接分隔字符,默认是[tab]来分隔。-:如果file部分写成-,表示来自标准输入的数据的意思。
expand
expand命令时将[tab]按键转化为空格键。
bash
expand [-t] file
-t:后面可接数字,一般来说一个Tab按键可以用8个空格键替换,这个参数可自定义一个[tab]代表几个字符。
6.5 划分命令:split
bash
split [-bl] file PREFIX
-
-b:后面可接欲划分成的文件大小,可加单位,例如b、k、m等。 -
-l:以行数来进行划分。 -
PREFIX:代表前缀字符的意思,可作为划分文件的前缀文字。6.6 参数代换:xargs
xargs就是产生某个命令参数的意思。xarge可以读取stdin的数据,并且以空格或换行符作为识别符,将stdin的数据分隔为参数。
bash
xarge [-0epn] command
-O:如果输入的stdin含有特殊字符,如 `、\、空格等,这个参数可以将它还原成一般字符。-e:这是EOF的意思,后面可以再接一个字符,当xarge分析到这个字符时,就会停止工作。-p:在执行每一个命令时都会询问使用者的意思。-n:后面接次数,每次command命令执行时,要是有几个参数的意思。- 当xarge没有接任何参数时,默认是以echo来进行输出。