11.认识与学习bash
11.1 认识bash这个shell
管理整个计算机硬件的其实是操作系统的核心 (kernel),这个核心是需要被保护的! 所以我们一般使用者就只能透过 shell 来跟核心沟通,以让核心达到我们所想要达到的工作。
11.1.1 硬件、内核与shell关系
11.1.2 为何要学习命令行界面的shell
-
文字接口的 shell :大家都一样!几乎各家 distributions 使用的 bash 都是一样的!如此一来, 你就能够轻轻松松的转换不同的 distributions ,就像武侠小说里面提到的『一法通、万法通!』
-
远程管理:文字接口就是比较快!Linux 的管理常常需要透过远程联机,而联机时文字接口的传输速度一定比较快, 而且,较不容易出现断线或者是信息外流的问题,因此,shell 真的是得学习的一项工具。
-
Linux 的任督二脉: shell 是也!
11.1.3 系统的合法shell和/etc/shells功能
早年的unix发展版本众多,所有shell依据发展版本不同,发展出多个版本。例如常用的bourne shell,sun里默认的c shell,商业上常 用 的k shell,还有TCSH等,每一种 Shell 都各有其特点。至于 Linux 使用的这一种版本就称为『 Bourne Again SHell (简称 bash) 』,这个 Shell 是 Bourne Shell 的增强版本,也是基准于 GNU 的架构下发展出来的。
那么目前我们的 Linux (以 CentOS 7.x 为例) 有多少我们可以使用的 shells 呢? 你可以检查一下/etc/shells 这个文件,至少就有底下这几个可以用的 shells:
- /bin/sh (已经被/bin/bash所取代)
- /bin/bash (linux 默认的shell)
- /bin/ksh (kornshell 由AT&T Bell lab 发展出来,兼容bash)
- /bin/tash :整合c shell,提供更多功能
- /bin/csh : 已经被/bin/tash 取代
- /bin/zsh : 基于ksh发展出来,功能更加强大的shell
虽然各家 shell 的功能都差不多,但是在某些语法的下达方面则有所不同,因此建议你还是得要选择某一种 shell 来熟悉一下较佳。 Linux 预设就是使用 bash ,所以最初你只要学会 bash 就非常了不起了!
11.1.4 bash shell的功能
bash shell的优点:
- 命令记忆功能 (history) :我只要在指令列按『上下键』就可以找到前/后一个输入的指令!而在很多 distribution 里头,默认的指令记忆功能可以到达 1000 个!也就是说,你曾经下达过的指令几乎都被记录下来了。这么多的指令记录在哪里:记录在你的家目录内的的 .bash_history文件夹中,~/.bash_history 。最大的好处就是可以『查询曾经做过的举动!』。~/.bash_history 记录的是前一次登入以前所执行过的指令, 而至于这一次登入所执行的指令都被暂存在内存,当你成功的注销系统后,该指令记忆才会记录到 .bash_history 当中!
- 命令与文件补全功能 ([Tab] 按键)
- 命令别名设置功能 (alias)你可以在指令列输入 alias 就可以知道目前的命令别名有哪些了!也可以直接下达命令来设定别名: $ alias lm='ls -al'
- 作业控制、前台、后台控制,(job controll 、 foreground 、background):使用前、背景的控制可以让工作进行的更为顺利!
至于工作控制(jobs)的用途则更广, 可以让我们随时将工作丢到背景中执行!而不怕不小心使用了[Ctrl] + c 来停掉该程序! - 程序化脚本: (shell scripts)
- 通配符( wildcard):除了完整的字符串之外, bash 还支持许多的通配符来帮助用户查询与指令下达。 举例来说,想要知道 /usr/bin 底下有多少以 X 为开头的文件吗?使用:『 ls -l /usr/bin/X* 』
11.1.5 bash的内置命令type
如何知道一个命令是来自于外部(指的是其他非 bash 所提供的指令) 还是内置的bash命令,利用 type 这个指令来观察即可
$ type [-tpa] name
#选项与参数:
#:不加任何选项与参数时,type 会显示出 name 是外部指令还是 bash 内建指令
#-t :当加入 -t 参数时,type 会将 name 以底下这些字眼显示出他的意义:
#1.file :表示为外部指令;
#2.alias :表示该指令为命令别名所设定的名称;
#3.builtin :表示该指令为 bash 内建的指令功能;
#-p :如果后面接的 name 为外部指令时,才会显示完整文件名;
#-a :会由 PATH 变量定义的路径中,将所有含 name 的指令都列出来,包含 alias
范例:
11.1.6 命令的执行
当你所需要下达的指令特别长,利用『 \[Enter] 』来将 [Enter] 这个按键『跳脱!』开来,让 [Enter] 按键不再具有『开始执行』的
功能!好让指令可以继续在下一行输入。 需要特别留意, [Enter] 按键是紧接着反斜杠 (\) 的,两者中间没有其他字符。 因为 \ 仅跳脱『紧接着的下一个字符』而已!
组合键 | 功能与示范 |
---|---|
[ctrl]+u/[ctrl]+k | 分别是从光标处向前删除指令串 ([ctrl]+u) 及向后删除指令串 ([ctrl]+k)。 |
[ctrl]+a/[ctrl]+e | 分别是让光标移动到整个指令串的最前面 ([ctrl]+a) 或最后面 ([ctrl]+e)。 |
11.2 shell的变量功能
变量是 bash 环境中非常重要的一个玩意儿,我们知道 Linux 是多人多任务的环境,每个人登入系统都能取得一个 bash shell, 每个人都能够使用 bash 下达 mail 这个指令来收受『自己』的邮件等等。问题是, bash 是如何得知你的邮件信箱是哪个文件? 这就需要『变量』的帮助啦!所以,变量很重要。
11.2.1 什么是变量
什么是『变量』,讲的更简单一点,我们可以『用一个简单的 "字眼" 来取代另一个比较复杂或者是容易变动的数据』。最大的好处就是『方便!』
11.2.2 变量的显示与设置: echo,unset
a).变量的显示/变数的取用
变量的取用就如同上面的范例,利用 echo 就能够读出,只是需要在变量名称前面加上 $ , 或者是以 ${变量} 的方式来取用都可以!当然啦,那个 echo 的功能可是很多的, 我们这里单纯是拿 echo来读出变量的内容而已。
b).变量的设定
- 变量与变量名以一个等号 “=”来连接 ,如『myname=VBird』;
- 等号两边不能直接接空格符
- 变量名称只能是英文字母与数字,但是开头字符不能是数字
- 变量内容若有空格符可使用双引号『"』或单引号『'』将变量内容结合起来。但
o 双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:
『var="lang is $LANG"』则『echo $var』可得『lang is zh_TW.UTF-8』
o 单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
『var='lang is $LANG'』则『echo $var』可得『lang is $LANG』 - 可以使用转义字符将特殊字符转换为一般字符。如\Enter 、 \$ 空格符、!等
- 在一串指令的执行中,还需要藉由其他额外的指令所提供的信息时,可以使用反单引号『`指令`』或 『$(指
令)』。如:『version=$(uname -r)』再『echo $version』可得『3.10.0-229.el7.x86_64』。 - 若该变量为扩增变量内容时,则可用 "$变量名称" 或 ${变量} 累加内容,如:『PATH="$PATH":/home/bin』或『PATH=${PATH}:/home/bin』
- 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量:『export PATH』;
- 通常大写字符为系统默认变量,自行设定变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;
- 取消变量的方法为使用 unset,如:『unset 变量名称』例如取消 myname 的设定:
『unset myname』
11.2.3 环境变量的功能
a).用env查看环境变量与常见环境变量说明(env environment (环境的缩写))
上面的例子当中,是列出来所有的环境变量。当然,如果使用export 也会是一样的内容~ 只不过, export 还有其他额外的功能。
那么上面这些变量有些什么功用呢?底下我们就一个一个来分析分析!
- HOME :代表用户主文件夹。
- SHELL:告知我们目前这个环境使用的shell是哪个程序?linux默认使用的是/bin/bash;
- HISTSIZE:这个与历史命令有关,即我们曾经使用的历史命令被记录下来,记录的条数由这个值设置;
- MAIL:当使用mail命令收信时,会获取这个值
- PATH:就是执行文件搜寻的路径~,目录与目录中间以冒号(:)分隔, 由于文件的搜寻是依序由 PATH 的变量内的
目录来查询,所以,目录的顺序也是重要! - LANG:这个重要,就是语系数据,很多信息都会用到它。
- RANDOM:这是随机数变量。
b).用set 查看所有变量(含有环境变量与自定义变量)
bash 可不只有环境变量,还有一些与 bash 操作接口有关的变量,以及用户自己定义的变量存在的。 set 除了环境变量之外, 还
会将其他在 bash 内的变量通通显示出来哩!信息很多,底下鸟哥仅列出几个重要的内容:
那么上头那些变量当中,大概有几个比较重要的:
- PS1:(提示字符的设定)(数字的 1 不是英文字母): 当我们每次按下 [Enter] 按键去执行某个指令后,最后要再次出现提示字符时, 就会主动去读取这个变数值了。上头 PS1 内显示的是一些特殊符号,这些特殊符号可以显示不同的信息,
\d :可显示出『星期 月 日』的日期格式,如:"Mon Feb 2"
\H :完整的主机名。举例来说,鸟哥的练习机为『study.centos.vbird』
\h :仅取主机名在第一个小数点之前的名字,如鸟哥主机则为『study』后面省略
\t :显示时间,为 24 小时格式的『HH:MM:SS』
\T :显示时间,为 12 小时格式的『HH:MM:SS』
\A :显示时间,为 24 小时格式的『HH:MM』
\@ :显示时间,为 12 小时格式的『am/pm』样式
\u :目前使用者的账号名称,如『dmtsai』;
\v :BASH 的版本信息,如鸟哥的测试主机版本为 4.2.46(1)-release,仅取『4.2』显示
\w :完整的工作目录名称,由根目录写起的目录名称。但家目录会以 ~ 取代;
\W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名。
\# :下达的第几个指令。
\$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $ 啰~ - $ (关于本 shell 的 PID):钱字号本身也是个变量!代表的是『目前这个 Shell 的线程代号』,亦即是所谓的 PID(Process ID)。
- ?:(关于上个执行指令的回传值)这个变数是:『上一个执行的指令所回传的值』, 上面这句话的重点是『上一个指令』与『回传值』两个地方。当我们执行某些指令时, 这些指令都会回传一个执行后的代码。一般来说,如果成功的执行该指令,则会回传一个 0 值,如果执行过程发生错误,就会回传『错误代码』才对!一般就是以非为 0 的数值来取代。
- OSTYPE, HOSTTYPE, MACHTYPE:(主机硬件与核心的等级)目前个人计算机的 CPU 主要分为 32/64 位,其中 32 位又可分为 i386, i586, i686,而 64 位则称为 x86_64。 由于不同等级的CPU 指令集不太相同,因此你的软件可能会针对某些 CPU 进行优化,以求取较佳的软件性能。所以软件就有 i386, i686 及 x86_64 之分。
c)使用export:自定义变量转成环境变量
谈了 env 与 set 现在知道有所谓的环境变量与自定义变量,那么这两者之间有啥差异呢?其实这两者的差异在于『 该变量是否会被子程序所继续引用』.那么啥是父程序?子程序?当你登入 Linux 并取得一个 bash 之后,你的 bash 就是一个独立的程序,这个程序的识别使用的是一个称为程序标识符,被称为 PID 的就是。 接下来你在这个 bash 底下所下达的任何指令都是由这个 bash 所衍生出来的,那些被下达的指令就被称为子程序了。
这个程序概念与变量有啥关系啊?关系可大了!因为子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量啦!所以你在原本 bash 的自定义变量在进入了子程序后就会消失不见,一直到你离开子程序并回到原本的父程序后,这个变量才会又出现!
11.2.4 影响显示结果的语系变量(local)
是当我们使用 man command 的方式去查询某个数据的说明文件时,该说明档的内容可能会因为我们使用的语系不同而产生乱码。 另外,利用 ls 查询文件的时间时,也可能会有乱码出现在时间的部分。那个问题其实就是语系的问题啦。
目前大多数的 Linux distributions 已经都是支持日渐流行的万国码了,也都支持大部分的国家语系。那么我们的 Linux 到底支持了多少的语系呢?这可以由 locale 这个指令来查询到!
整个系统定义的默认语系在/etc/sysconfig/i18n
11.2.5 变量的有效范围
我们在上头的 export 指令说明中,提到了这个概念了。如果在跑程序的时候,有父程序与子程序的不同程序关系时, 则『变量』可否被引用与 export 有关。被 export 后的变量,我们可以称他为『环境变量』! 环境变量可以被子程序所引用,但是其他的自定义变量内容就不会存在于子程序中。
在学理方面,为什么环境变量的数据可以被子程序所引用呢?这是因为内存配置的关系!理论上是这样的:
- 当启动一个 shell,操作系统会分配一记忆区块给 shell 使用,此内存内之变量可让子程序取用
- 若在父程序利用 export 功能,可以让自定义变量的内容写到上述的记忆区块当中(环境变量);
- 当加载另一个 shell 时 (亦即启动子程序,而离开原本的父程序了),子 shell 可以将父 shell 的环境变量所在的记忆区块导入自己的环境变量区块当中。
11.2.6变量的键盘读取、数组与声明:read、array、declare
a).读入来自键盘的变量:read
read 之后不加任何参数,直接加上变量名称,那么底下就会主动出现一个空白行等待你的输入(如范例一)。 如果加上 -t 后面接秒数,例如上面的范例二,那么 30 秒之内没有任何动作时, 该指令就会自动略过了~如果是加上 -p ,嘿嘿!在输入的光标前就会有比较多可以用的提示字符给我们参考!
b).声明变量的类型:declare / typeset
declare 或 typeset 是一样的功能,就是在『宣告变量的类型』。
由于在默认的情况底下, bash 对于变量有几个基本的定义:
- 变量类型默认为『字符串』,所以若不指定变量类型,则 1+2 为一个『字符串』而不是『计算式』。 所以上述第一个执行的结果才会出现那个情况的;
- bash 环境中的数值运算,预设最多仅能到达整数形态,所以 1/3 结果是 0;
declare 也是个很有用的功能~尤其是当我们需要使用到底下的数组功能时, 他也可以帮我们宣告数组的属性喔!数组也是在 shell script 比较常用的啦! 比较有趣的是,如果你不小心将变量设定为『只读』,通常得要注销再登入才能复原该变量的类型了!
c).数组 (array) 变量类型
数组的变量类型比较有趣的地方在于『读取』,一般来说,建议直接以 ${数组} 的方式来读取,比较正确无误的啦!这也是为啥鸟哥一开始就建议你使用 ${变量} 来记忆的原因!
11.2.7 与文件系统及程序的限制关系:ulimit
想象一个状况:我的 Linux 主机里面同时登入了十个人,这十个人不知怎么搞的, 同时开启了 100个文件,每个文件的大小约 10MBytes ,请问一下, 我的 Linux 主机的内存要有多大才够?10*100*10 = 10000 MBytes = 10GBytes ... 老天爷,这样,系统不挂点才有鬼哩!为了要预防这个情况的发生,所以我们的 bash 是可以『限制用户的某些系统资源』的,包括可以开启的文件数量, 可以使用的 CPU 时间,可以使用的内存总量等等。
11.2.8 变量内容的删除、替代、与替换
a). 变量内容的删除与取代
上面这个范例很有趣的!他的重点可以用底下这张表格来说明:
因为在 PATH 这个变量的内容中,每个目录都是以冒号『:』隔开的, 所以要从头删除掉目录就是介于斜线 (/) 到冒号 (:) 之间的数据!但是 PATH 中不止一个冒号 (:) 啊! 所以 # 与 ## 就分别代表:
- # :符合取代文字的『最短的』那一个;
- ##:符合取代文字的『最长的』那一个
总结:
变量设定方式 | 说明 |
---|---|
${变量#关键词} ${变量##关键词} | 若变量内容从头开始的数据符合『关键词』,则将符合的最短数据删除 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据删除 |
${变量%关键词} ${变量%%关键词} | 若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据删除 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据删除 |
${变量/旧字符串/新字符串} ${变量//旧字符串/新字符串} | 若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串取代』 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串取代』 |
b).变量的测试与内容替换
在某些时刻我们常常需要『判断』某个变量是否存在,若变量存在则使用既有的设定,若变量不存在则给予一个常用的设定。
不过这还是有点问题!因为 username 可能已经被设定为『空字符串』了!果真如此的话,那你还可以使用底下的范例来给予 username 的内容成为 root !
在大括号内有没有冒号『 : 』的差别是很大的!加上冒号后,被测试的变量未被设定或者是已被设定为空字符串时, 都能够用后面的内容 (本例中是使用 root 为内容) 来替换与设定!
整理:
变量设定方式 | 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 |
基本上这种变数的测试也能够透过 shell script 内的 if...then... 来处理, 不过既然 bash 有提供这么简单的方法来测试变量,那我们也可以多学一些嘛! 不过这种变量测试通常是在程序设计当中比较容易出现,如果这里看不懂就先略过,未来有用到判断变量值时,再回来看看吧!
11.3 命令别名与历史命令
11.3.1 命令别名设置:alias 、 unalias
命令别名是一个很有趣的东西,特别是你的惯用指令特别长的时候!还有, 增设默认的选项在一些惯用的指令上面,可以预防一些不小心误杀文件的情况发生的时候! 举个例子来说,如果你要查询隐藏档,并且需要长的列出与一页一页翻看,那么需要下达『 ls -al | more 』这个指令,鸟哥是觉得很烦啦! 要输入好几个单字!那可不可以使用 lm 来简化呢?当然可以,你可以在命令行下面下达:
立刻多出了一个可以执行的指令喔!这个指令名称为 lm ,且其实他是执行 ls -al | more 啊
另外,命令别名的设定还可以取代既有的指令喔!举例来说,我们知道 root 可以移除 (rm) 任何数据!所以当你以 root 的身份在进行工作时,需要特别小心, 但是总有失手的时候,那么 rm 提供了一个选项来让我们确认是否要移除该文件,那就是 -i 这个选项!所以,你可以这样做:
11.3.2 历史命令:history
如何查询我们曾经下达过的指令呢?就使用history
语法:
在正常的情况下,历史命令的读取与记录是这样的:
- 当我们以 bash 登入 Linux 主机之后,系统会主动的由家目录的 ~/.bash_history 读取以前曾经下过的指令,那么 ~/.bash_history 会记录几笔数据呢?这就与你 bash 的 HISTFILESIZE 这个变量设定值有关了!
- 假设我这次登入主机后,共下达过 100 次指令,『等我注销时, 系统就会将 101~1100 这总共 1000 笔历史命令 更新到 ~/.bash_history 当中。』 也就是说,历史命令在我注销时,会将最近的 HISTFILESIZE 笔记录到我的纪录文件当中啦!
- 当然,也可以用 history -w 强制立刻写入的!那为何用『更新』两个字呢? 因为 ~/.bash_history 记录的笔数永远都是 HISTFILESIZE 那么多,旧的讯息会被主动的拿掉! 仅保留最新的!
那么 history 这个历史命令只可以让我查询命令而已吗?当然不止啊! 我们可以利用相关的功能来帮我们执行命令呢!举例来说:
11.4 bash shell的操作环境
11.4.1路径与命令查找顺序
现在我们知道系统里面其实有不少的 ls 指令, 或者是包括内建的 echo 指令,那么来想一想,如果一个指令 (例如 ls) 被下达时, 到底是哪一个 ls 被拿来运作?基本上命令的运行顺序可以这样看:
- 以相对路径或者绝对路径执行命令。例如"/bin/ls" 、"./ls"
- 由alias 找到命令来执行
- 由bash内置的(builtin)命令来执行
- 通过PATH这个变量来查找到第一个命令来执行
11.4.2 bash的登录与欢迎信息:/etc/issue 、 /etc/motd
还记得在终端机接口 (tty1 ~ tty6) 登入的时候,会有几行提示的字符串吗?那就是进站画面! 那个字符串写在 /etc/issue里面!先来看看:
issue 这个文件的内容也是可以使用反斜杠作为变量取用喔!你可以 man issue 配合 man agetty 得到底下的结果:
\d:本地端的时间
\l:显示第几个中断接口
\m:显示硬件等级(i386/i486)
\n:显示主机网络名称
\o:显示 domain name
\r:操作系统的版本 相当于 uname -r
\t:显示本地端时间的时间
\s:操作系统名称
\v:操作系统的版本
11.4.3 bash的环境配置文件
你是否会觉得奇怪,怎么我们什么动作都没有进行,但是一进入 bash 就取得一堆有用的变量了? 这是因为系统有一些环境配置文件案的存在,让 bash 在启动时直接读取这些配置文件,以规划好 bash的操作环境啦! 而这些配置文件又可以分为全体系统的配置文件以及用户个人偏好配置文件。要注意的是, 我们前几个小节谈到的命令别名啦、自定义的变数啦,在你注销 bash 后就会失效,所以
你想要保留你的设定, 就得要将这些设定写入配置文件才行。
a) login 与nologin shell
在开始介绍 bash 的配置文件前,我们一定要先知道的就是 login shell 与 non-login shell! 重点在于有没有登入 (login) 啦!
- login shell:取得 bash 时需要完整的登入流程的,就称为 login shell。举例来说,你要由 tty1 ~ tty6 登入,需要输入用户的账号与密码,此时取得的 bash 就称为『 login shell 』。
- non-login shell:取得 bash 接口的方法不需要重复登入的举动,举例来说,(1)你以 X window 登入 Linux 后,再以 X 的图形化接口启动终端机,此时那个终端接口并没有需要再次的输入账号与密码,那个 bash 的环境就称为 non-login shell 了。(2)你在原本的 bash 环境下再次下达 bash 这个指令,同样的也没有输入账号密码, 那第二个 bash (子程序) 也是 non-login shell 。
为什么要介绍 login, non-login shell 呢?这是因为这两个取得 bash 的情况中,读取的配置文件数据并不一样所致。 由于我们需要登入系统,所以先谈谈 login shell 会读取哪些配置文件?一般来说,login shell 其实只会读取这两个配置文件:
- /etc/profile:这是系统整体的设定,你最好不要修改这个文件;
- ~/.bash_profile 或 ~/.bash_login 或 ~/.profile:属于使用者个人设定,你要改自己的数据,就写入这里!
我们来聊一聊这/etc/profile、~/.bash_profile ,两个文件吧!这两个文件的内容可是非常繁复:
b) /etc/profile(login shell 才会读):
你可以使用 vim 去阅读一下这个文件的内容。这个配置文件可以利用使用者的标识符 (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 默认的情况下,底下这些数据会依序的被呼叫进来:
- /etc/profile.d/*.sh:其实这是个目录内的众多文件!只要在 /etc/profile.d/ 这个目录内且扩展名为 .sh ,另外,使用者能够具有 r 的权限, 那么该文件就会被 /etc/profile 呼叫进来。在 CentOS 7.x 中,这个目录底下的文件规范了 bash 操作接口的颜色、 语系、ll 与 ls 指令的命令别名、vi 的命令别名、which的命令别名等等。如果你需要帮所有使用者设定一些共享的命令别名时, 可以在这个目录底下自行建立扩展名为 .sh 的文件,并将所需要的数据写入即可。
- /etc/locale.conf:这个文件是由 /etc/profile.d/lang.sh 呼叫进来的!这也是我们决定 bash 预设使用何种语系的重要
配置文件! - /usr/share/bash-completion/completions/*
c) ~/.bash_profile (login shell 才会读)
bash 在读完了整体环境设定的 /etc/profile 并藉此呼叫其他配置文件后,接下来则是会读取使用者的个人配置文件。 在 login shell 的 bash 环境中,所读取的个人偏好配置文件其实主要有三个,依序分别是:
- ~/.bash_profile
- ~/.bash_login
- ~/.profile
其实 bash 的 login shell 设定只会读取上面三个文件的其中一个, 而读取的顺序则是依照上面的顺序。也就是说,如果 ~/.bash_profile 存在,那么其他两个文件不论有无存在,都不会被读取。 如果~/.bash_profile 不存在才会去读取 ~/.bash_login,而前两者都不存在才会读取 ~/.profile 的意思。
d) source :读入环境配置文件的指令
由于 /etc/profile 与 ~/.bash_profile 都是在取得 login shell 的时候才会读取的配置文件,所以, 如果你将自己的偏好设定写入上述的文件后,通常都是得注销再登入后,该设定才会生效。那么,能不能直接读取配置文件而不注销登入呢? 可以的!那就得要利用 source 这个指令了!
non-login shell 会读
~/.bashrc
e)其他配置文件
/etc/man.config
这个文件规定了使用man page 的路径去哪里去找。简单说 这个文件规定了执行man的时候该去哪里查看数据
~/.bash_history
默认情况下 我们的历史命令就会记录到这里。
~/.bash_logout
这个文件记录 当我们注销bash后,系统帮我们在做什么 我们再离开
11.4.4 终端机的环境设置
事实上,目前我们使用的 Linux distributions 都帮我们作了最棒的使用者环境了, 所以大家可以不用担心操作环境的问题。不过,在某些 Unix like 的机器中,还是可能需要动用一些手脚, 才能够让我们的输入比较快乐~举例来说,利用 [backspace] 删除,要比利用 [Del] 按键来的顺手吧! 但是某些 Unix 偏偏是以 [del] 来进行字符的删除啊!所以,这个时候就可以动动手脚啰~.。
那么如何查阅目前的一些按键内容呢?可以利用 stty (setting tty 终端机的意思) 呢! stty 也可以帮助设定终端机的输入按键代表意义喔!
在上头的列表当中,需要注意的是特殊字体那几个, 此外,如果出现 ^ 表示 [Ctrl] 那个按键的意思。举例来说, intr = ^C 表示利用 [ctrl] +
c 来达成的。几个重要的代表意义是:
- intr : 送出一个 interrupt (中断) 的讯号给目前正在 run 的程序 (就是终止啰!);
- quit : 送出一个 quit 的讯号给目前正在 run 的程序;
- erase : 向后删除字符,
- kill : 删除在目前指令列上的所有文字;
- eof : End of file 的意思,代表『结束输入』。
- start : 在某个程序停止后,重新启动他的 output
- stop : 停止目前屏幕的输出;
- susp : 送出一个 terminal stop 的讯号给正在 run 的程序。
除了 stty 之外,其实我们的 bash 还有自己的一些终端机设定值呢!那就是利用 set 来设定的! 我们之前提到一些变量时,可以利用 set 来显示,除此之外,其实 set 还可以帮我们设定整个指令输出/输入的环境。
最后,我们将 bash 默认的组合键给他汇整如下:
组合按键 | 执行结果 |
---|---|
Ctrl + C | 终止目前的命令 |
Ctrl + D | 输入结束 (EOF),例如邮件结束的时候; |
Ctrl + M | 就是 Enter 啦! |
Ctrl + S | 暂停屏幕的输出 |
Ctrl + Q | 恢复屏幕的输出 |
Ctrl + U | 在提示字符下,将整列命令删除 |
Ctrl + Z | 『暂停』目前的命令 |
11.4.5通配符与特殊符号
底下我们列出一些常用的通配符:
符号 | 意义 |
* | 代表『 0 个到无穷多个』任意字符 |
? | 代表『一定有一个』任意字符 |
[ ] | 同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符, 可能是 a, b,c, d 这四个任何一个』 |
[ - ] | 若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字,因为数字的语系编码是连续的! |
[^ ] | 若中括号内的第一个字符为指数符号 (^) ,那表示『反向选择』,例如 [^abc] 代表 一定有一个字符,只要是非 a, b, c 的其他字符就接受的意思。 |
除了通配符之外,bash 环境中的特殊符号有哪些呢?底下我们先汇整一下:
符号 | 内容 |
# | 批注符号:这个最常被使用在 script 当中,视为说明!在后的数据均不执行 |
\ | :转义符号 |
| | 管线 (pipe):分隔两个管线命令的界定(后两节介绍); |
; | 连续指令下达分隔符:连续性命令的界定 (注意!与管线命令并不相同) |
~ | 用户的家目录 |
$ | 取用变数前导符:亦即是变量之前需要加的变量取代值 |
& | 工作控制 (job control):将指令变成背景下工作 |
! | 逻辑运算意义上的『非』 not 的意思! |
/ | 目录符号:路径分隔的符号 |
>, >> | 数据流重导向:输出导向,分别是『取代』与『累加』 |
<, << | 数据流重导向:输入导向 (这两个留待下节介绍) |
' ' | 单引号,不具有变量置换的功能 ($ 变为纯文本) |
" " | 具有变量置换的功能! ($ 可保留相关功能) |
` ` | 两个『 ` 』中间为可以先执行的指令,亦可使用 $( ) |
( ) | 在中间为子 shell 的起始与结束 |
{ } | 在中间为命令区块的组合! |
11.5 数据流重定向
数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!这玩意儿在 Linux 的文本模式底下可重要的! 尤其是如果我们想要将某些数据储存下来时,就更有用了!
11.5.1 什么是数据流重定向
什么是数据流重导向啊?这得要由指令的执行结果谈起!一般来说,如果你要执行一个指令,通常他会是这样的:
我们执行一个指令的时候,这个指令可能会由文件读入资料,经过处理之后,再将数据输出到屏幕上。在上图当中, standard output 与 standard error output 分别代表『标准输出 (STDOUT)』与『标准错误输出 (STDERR)』, 这两个玩意儿默认都是输出到屏幕上面来的啊!
standard output 与standard error output
1>:以覆盖的方式将正确的数据输入到指定文件或者设备上
1>>:以累加的方式将....
2>:以覆盖的方式将错误数据....
2>>:以累加的方式将....
例如:将正确信息和错误信息分别放到不同的文件中
> find /home -name .barsh > list_right 2>list_error
dev/null 垃圾桶黑洞设备与特殊写法
dev/null可以将任何导向这个文件的信息吃掉。
例如:不在屏幕输入错误信息,也不写入文件
>find /home -name dddd 2>/dev/null
standard input : <与<<
11.5.2 命令执行的判断依据: && || , ;
不考虑命令相关性的连续命令执行:cmd1;cmd2
$?(命令回传码) 与 && 或 ||
两个命令有相依性
cmd1 && cmd2 :若cmd1执行完毕且正确执行($? =0) 和执行cmd2
cmd1 || cmd2 :若cmd1 执行完毕且且为错误($? 不等于 0) 则执行cmd2
11.6 管道命令pipe
11.6.1 选取命令 cut 和grep
cut:将一段信息切出来
语法:
>cut -d'分隔符' -f fields
>cut -c 字符范围
-d : 后面接分割字符 与-f一起使用
-f:依据-d 的分割字符,将一段信息切割成为数段,-f 选取第几端的意思
-c :以字符为单位取出固定的字符区间
cut的主要用途在于同一行里面的数据进行分解,进行切割以去的我们想要的数据;
例子:
>echo %PATH | cut -d ';' -f 5
以分号分割,并取出第五个
>echo %PATH | cut -d ';' -f 5,3
取第3 和5个
>echo %PATH | cut -c 12-
取12个后的所有字符
>echo %PATH | cut -c 12-20
取 12到第20个
grep 命令
分析一行信息,如果该行有我们要的数据,就将该行那出来;
语法:
grep [-avinv] [--color=auto] '查找字符串' filename
-a:将binary 文件以text的文化的方式查找数据;
-c:计算找到 “字符串”的次数
-i:忽略大小写
-n:顺便输出行号
-v:反向选择,即显示出没有 查找字符串的那一行
--color=auto: 可以将找到关键字加上颜色;
11.6.2 排序命令 sort 、wc、uniq
sort:帮我们进行排序
语法
>sort [-fbMnrtuk] [file or stdin]
-f:忽略大小写的差异
-b:忽略最前面空格的部分
-M:以月份的名字来排序,如JAN,DEC
-n:使用纯数字来排序(默认是以文字类型来排序的)
-r:反向排序
-u:就是uniq,相同的数据只出现一次
-t:分隔符,默认是[Tab]键来分割
-k:以哪个区间 (filed)来进行排序的意思
例子:
将内容以:分割,并以第三列来排序
>cat /etc/pass -t ';' -k 3
uniq:如果排序完成,想要将重复的数据仅显示一列
>uniq [-ic]
-i:忽略大小写
-c:进行计数
例子
使用last将账号列出来,仅取出账号列,进行排序后仅取出一位
>last | cut -d ' ' -f1 | sort |uniq
wc : 计算输出信息的整体数据,例如 /etc/man.config 这个文件有多少字,多个行,多少个字符。
语法
>wc [-lwm]
-l:仅列出行
-w:仅列出多少个字(英文单词)
-c:多少个字符
11.6.3 双向重定向:tee
> 会将数据流整个传送给文件或者设备,因此除非去读取这个文件或设备,否则就无法继续使用这个数据流
tee 会将数据流送与文件和屏幕,可以让下个命令继续使用
语法:
>tee [-a] file
-a : 以累加的方式输入的到文件
例子
>last | tee last.list |cut -d “ ”-f1
11.6.4 字符串转换命令:tr,col,join,paste,expand
tr 可以用来删除一段信息当中的文字,或者进行文字信息的替换
语法:
>tr [-ds] SET1
-d:删除信息当中的SET1这个字符串
-s : 替换掉重复的字符
例子:
将last 输入信息中的所有小写字母替换成大写字母
>last | tr [a-z] [A-Z]
将/etc/passwd 输出信息中的 冒号删除
>cat /etc/passwd | tr -d ':'
col
语法:
>col [-xb]
-x:将 [Tab] 键替换成相等的 空格
-b:在文件内有反斜杠时,仅保留反斜杠最后接的那个字符
join :处理两个文件的数据,将两个文件当中,有相同数据的那一行加到一起
语法:
>join [-ti12] file1 file2
-t :join 默认以空格分隔数据,并且对比”第一个字段“的数据 如果两个文件相同,则键两条数据连连城一行;且第一个字段放在第一个个
-i:忽略大小写
-1:数字1 ,代表第一个文件要用哪个字段来分析的意思
-2:数字2,代表第二个文件要用哪个字段来分析的意思
paste:这个要比join简单的多,join必须要对比两个文件的相关性,而paste就是直接将两行贴在一起。
语法
>paste [-d] file1 file2
-d:后面可以接分隔符,默认是以 [Tab] 来分割
-:如果file 部分写成了 - ,代表标准输入
expand :就是将[Tab] 键转换成空格
语法:
>expand [-t] file
-t:后面接数字,自定义一个tab 替换成多少个空格
11.6.5 切割命令: split
如果文件太大,导致一些便携设备无法复制粘贴,可以使用split,将大文件切成若干小文件
语法:
>spilt [-bl] file PREFIX
-b:后面接欲切成的文件大小 ,可接单位 如b k m等
-l:以行数来进行切割
PREFIX:代表前导符,可作为可切割文件的前导文字
11.6.6 参数代换:xargs
args 是arguments的缩写,xargs是 产生某个命令的参数。xargs可以读入stdin的数据,并且以空格或者断行字符进行分辨,将stdin的数据分割成argumens。因为是以空格符进行分割的,如果一些文件或者其他意义的名词中含有空格时,xargs可能会出现误判
语法
>xargs [-0epn] command
-0:如果输入stdin含有特殊字符,例如 \ 空格键等字符信息时,这个参数可以将它还原成一般字符,这个参数参数可以用于特殊状态
-e:这个是EOF 的意思,后面可以接一个字符串,当xargs 分析到这个字符串时,就会停止继续工作
-p:在执行每个命令的参数时,都会询问用户的意思
-n:后面接次数,每次command执行时,要使用几个参数的意思。
11.6.7 关于减号-的用途
在管道命令中,经常会使用前一个明林的stdout作为这次的stdin,某些命令需要用到文件名在处理时,该stdin与stdout可以使用减号来替代