1、bash 与 shell
管理整个计算机硬件的其实是操作系统的内核(Kernel),这个内核是需要被保护的,所以我们一般用户就只能通过shell来跟内核通信,让内核达到我们想要达到的工作。
1.1、硬件,内核与shell
我们必须通过 shell 将我们输入的命令与内核通信,好让内核可以控制硬件来正确无误的工作。
操作系统其实是一组软件,由于这组软件在控制整个硬件与管理系统的活动监测。如果这组软件能被用户随意操作,若用户应用不当,将会使得整个系统奔溃。因为操纵系统管理的就是整个硬件功能,所以当然不能够被随便一些没有管理能力的终端用户随意使用。
但我们总是需要让用户操作系统的,所以就有了在操作系统上面发展的应用程序。用户可以通过应用程序来指挥内核,让内核达到我们所需要的硬件任务。
如图所示,其实应用程序在最外层,就如同鸡蛋的外壳一样,因此这个也就被称为shell。
也就是说,只要能够操作应用程序的接口都能够称为shell。狭义的shell指的是命令行方面的软件,包括bash等。广义的shell则包括图形界面的软件。
1.2、为何要学习命令界面的shell
命令行界面的shell:各个distribution 都一样;
远程管理:命令行界面就是比较快;
Linux的任督二脉:shell是也;
1.3、系统的合法shell与/etc/shells功能
由于shell依据发布者的不同就有许多版本,例如 Bourne SHell (sh)、C SHell、K SHell、TCSH等。
Linux默认使用的这一版本就是 Bourne Again SHell(bash),这个shell是 Bourne SHell 的增强版,也是基于GNU框架下发展出来的。
cat /etc/shells #检查系统有多少个可以使用的shell
为什么我们系统上合法的shell要写入/etc/shells这个文件?这是因为系统某些服务在运行过程中,会去检查用户能够使用的shells,而这些shell的查询就是借助/etc/shells这个文件。
我这个用户什么时候可以取得shell权限呢?默认又会取得哪一种shell呢?
cat /etc/passwd
每一行的最后一个数据,就是你可以取得的默认的shell。
1.4、bash shell 的功能
bash是GNU计划中重要的工具软件之一,目前也是Linux distributions 的标准shell。bash主要兼容于sh,并且依据一些用户的需求而加强shell 版本。
bash的主要优点:
命令记忆能力(history);
命令与文件补全功能(【tab】按键的好处);
命令别名设置功能(alias); # alias ll='ls -l'
作业控制、前台、后台控制(job control, foreground,background);
使用前台、后台的控制可以让作业进行得更为顺利。至于作业控制(jobs)的用途更广,可以让我们随时将工作丢到后台中执行,而不怕不小心使用 ctrl + c 来中断该进程。此外也可以在单一登录的环境中达到多任务的目的呢!
程序脚本(shell script);# 还记得DOS下的批处理文件吗?Linux下的shell script 则发挥更为强大的功能。
通配符(Wildcard);
1.5、bash shell 的内置命令:type
判定一个命令是来自于外部命令(非bash所提供的命令)或是内置在bash当中的呢?利用type这个命令来查看即可。
type 主要在找出“执行文件”而不是一般文件名,所以type也可以用来作为类似which命令的用途。
1.6、命令的执行
如果命令串太长的话,如何使用两行来输出?
cp /var/spool/mail/root /etc/crontab \
> /etc/fstab /root
上面的命令是将三个文件复制到/root这个目录下来,不过因为命令太长,我们就利用 “ \[Enter] " ,用转义符 " \ "来将 " [Enter]"转义,让 [Enter] 按键不再具有“开始执行”的功能。
特别要注意 转义字符 " \ ",这非常重要。
2、shell 的变量功能
2.1、什么是变量
y=ax+b,其中左边的y就是变量,右边的(ax+b)就是变量内容。左边是未知数,右边是已知数。
变量就是以一组文字或符号等,来替代一些设置或者是一串保留的数据。
讲的更简单一点,我们可以用一个简单的“字眼”来替代另一个比较复杂或者是容易变动的数据。这样最大的好处就是方便。
变量的可变性与方便性;
影响bash环境操作的变量;
脚本程序设计的好帮手;
2.2变量的显示与设置:echo、unset
你可以利用 echo 这个命令来显示变量,但是变量在被显示的时候,前面必须要加上字符 "$" 才行。
echo $PATH
echo $HOME
myname=Zhang
echo $myname
在bash中,当一个变量名称尚未被设置时,默认的内容是”空“的。
变量的设置规则
1,变量与变量内容以一个等号”=“来连接,如myname=zhang;
2,等号两边不能直接接空格符,否则错误;
3,变量名称只能是英文字母和数字,但是开头字符不能是数字;
4,变量内容若有空格可使用 双引号”“ 或者单引号‘’ 将变量内容结合起来;
双引号 " " 内的特殊符号(如$等),可以保有原本的特性。
单引号 ' ' 内的特殊字符则仅为一般字符(纯文本)。
5,可用转义字符 "\"将特殊符号(如 [Enter]、$、\、空格符、!等)变成一般字符;
6,在一串命令中,还需要通过其他命令提供的信息,可以使用 反单引号 ` `(~符号键,在1旁边,tab上边);
7,若该变量为了增加变量内容时,则可用 $变量名称 或 ${变量} 累加内容;
8,若该变量需要在其他子进程执行,则需要以 export 来使变量变成环境变量;
9,通常大写字符为系统默认变量,自行设置变量可以使用小写字符,方便判断;
0,取消标量的方法为使用 unset 变量名,如 unset myname;
什么是子进程?就是说在我目前这个shell的情况下,去打开另一个新的shell,新的那个shell就是子进程。在一般状态下,父进程定义的变量是无法在子进程内使用的,要通过 export 将变量变成环境变量后才可以。
在一串命令中,在 反引号 `` 内的命令将被优先执行,而其执行结果将作为外部的输入信息。
特别注意 单引号,双引号,反引号 所代表的意思。
2.3、环境变量的功能
环境变量可以帮我们达到很多功能,包括主文件夹的变换、提示符的显示、执行文件查找的路径等。
用env(environment)查看环境变量与常见环境变量说明:
HOME 代表用户主目录;
SHELL 告知我们目前这个环境使用的shell是哪个程序;
HISTSIZE 这个与历史命令有关;
PATH 就是执行文件查找的路劲;
LANG 系统语系数据;
RANDOM 这是随机数变量;
用set查看所有变量(含环境变量和自定义变量)
PS1这个是我们的命令提示符,PS2是第二行的提示符;
PS1:(提示字符的配置)
这是 PS1 (数字的 1 不是英文字母),这个东西就是我们的『命令提示字符』喔! 当我们每次按下 [Enter] 按键去运行某个命令后,最后要再次出现提示字符时, 就会主动去读取这个变量值了。上头 PS1 内显示的是一些特殊符号,这些特殊符号可以显示不同的信息, 每个 distributions 的 bash 默认的 PS1 变量内容可能有些许的差异,不要紧,『习惯你自己的习惯』就好了。 你可以用 man bash (注3)去查询一下 PS1 的相关说明,以理解底下的一些符号意义。
\d :可显示出『星期 月 日』的日期格式,如:"Mon Feb 2"
\H :完整的主机名。举例来说,鸟哥的练习机为『www.vbird.tsai』
\h :仅取主机名在第一个小数点之前的名字,如鸟哥主机则为『www』后面省略
\t :显示时间,为 24 小时格式的『HH:MM:SS』
\T :显示时间,为 12 小时格式的『HH:MM:SS』
\A :显示时间,为 24 小时格式的『HH:MM』
\@ :显示时间,为 12 小时格式的『am/pm』样式
\u :目前使用者的账号名称,如『root』;
\v :BASH 的版本信息,如鸟哥的测试主板本为 3.2.25(1),仅取『3.2』显示
\w :完整的工作目录名称,由根目录写起的目录名称。但家目录会以 ~ 取代;
\W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名。
\# :下达的第几个命令。
\$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $ 啰~
好了,让我们来看看 CentOS 默认的 PS1 内容吧:『[\u@\h \W]\$ 』,现在你知道那些反斜杠后的数据意义了吧? 要注意喔!那个反斜杠后的数据为 PS1 的特殊功能,与 bash 的变量配置没关系啦!不要搞混了喔! 那你现在知道为何你的命令提示字符是:『 [root@www ~]# 』了吧?
$:(关于本 shell 的 PID)
钱字号本身也是个变量喔!这个咚咚代表的是『目前这个 Shell 的线程代号』,亦即是所谓的 PID (Process ID)。 更多的程序观念,我们会在第四篇的时候提及。想要知道我们的 shell 的 PID ,就可以用:『 echo $$ 』即可!出现的数字就是你的 PID 号码。
什么?问号也是一个特殊的变量?没错!在 bash 里面这个变量可重要的很! 这个变量是:『上一个运行的命令所回传的值』, 上面这句话的重点是『上一个命令』与『回传值』两个地方。当我们运行某些命令时, 这些命令都会回传一个运行后的代码。一般来说,如果成功的运行该命令, 则会回传一个 0 值,如果运行过程发生错误,就会回传『错误代码』才对!
OSTYPE, HOSTTYPE, MACHTYPE:(主机硬件与核心的等级)
由于不同等级的 CPU 命令集不太相同,因此你的软件可能会针对某些 CPU 进行优化,以求取较佳的软件性能。 所以软件就有 i386, i686 及 x86_64 之分。
要留意的是,较高阶的硬件通常会向下兼容旧有的软件,但较高阶的软件可能无法在旧机器上面安装!
export: 自定义变量转成环境变量
因为子进程仅会继承父进程的环境变量,子进程不会继承父进程的自定义变量,所以需要使用 export 命令。
export 变量名称;
2.4、影响显示结果的语系变量(locale)
locale ;
设置LANG的时候,其他的语系变量就会被这个变量所替代。
2.5、变量的有效范围
某些书籍会谈到 全局变量(global variable)和 局部变量(local variable),基本上可以这么理解,
环境变量=全局变量;
自定义变量=局部变量;
2.6、变量键盘读取、数组与声明:read,array,declare
read
要读取来自键盘输入的变量,就是用read这个命令。
declare / typeset
declare 或 typeset 是一样的功能,就是在『声明变量的类型』
变量类型默认为 字符串,所以若不指定变量类型,则 1+2 为一个字符串而不是计算式;
bash 环境中的数值运算,默认最多仅能到达整数类型,所以 1/3 结果为 0;
数组(array)变量类型:
某些时候,我们必须使用数组来宣告一些变量。
数组的变量类型比较有趣的地方在于『读取』,一般来说,建议直接以 ${数组} 的方式来读取,比较正确无误的啦!
3、命令别名与历史命令
3.1、命令别名设置:alias,unalias
命令别名是一个很有趣的东西,特别是你的惯用命令特别长的时候。或者给命令增设默认选项的时候。
alias ll='ls -l'
source ~/.bashrc
查看系统别名情况
unalias ll #取消ll命令别名
3.2、历史命令:history
查看使用过的历史命令
history
那么history命令只可以让我们查询命令而已吗?当然不止。我们可以利用相关的功能来帮我们执行历史命令。
基本上history命令用途很大,但是需要小心安全的问题,尤其是root的历史纪录文件,这是Cracker的最爱。因为不小心 root 会将很多的重要数据在执行的过程中记录在 ~/.bash_history当中,如果这个文件被解析的话,后果不堪设想。
无论如何,使用history配置 !曾经使用的命令执行是很有效率的。
4、Bash Shell的操作环境
是否记得我们登录主机的时候屏幕上面会有一些说明文字,并且登录的时候还可以给用户提供一些信息或者欢迎文字。此外我们习惯的环境变量,命令别名等是否可以登录就主动帮我们设置好?
4.1、路径与命令查找顺序
命令的运行顺序基本上可以这样看:
1,以绝对/相对路径执行命令;
2,由alias找到该命令来执行;
3,由bash内置的(builtin)命令来执行;
4,通过$PATH这个变量的顺序找到的第一个命令来执行
4.2、bash的登录与欢迎信息:/etc/issue,/etc/motd
还记得在终端接口登录时候的欢迎信息吗?它在 /etc/issue 里面。可对此进行自定义。
cat /etc/issue
如果你想要让用户登录后取得一些信息,例如你想要让大家都知道的信息,那么可以将信息加入 /etc/motd 里去。所有用户都会显示这个信息。
vi /etc/motd
4.3、bash的环境配置文件
操作系统有一些环境配置文件的存在,让bash在启动时直接读取这些配置文件,以规划好bash的操作环境。而这些配置文件又可以分为全体系统的配置文件以及用户个人偏好配置文件。要注意的是,我们前几个小时谈到的命令别名、自定义的变量在你注销bash后就会失效,所以你想要保留你的设置,就得要将这些设置写入配置文件才行。
login shell 和 non-login shell
取得bash时需要完整的登录流程,就称为login shell。
取得bash接口的方法不需要重复登录的举动,就称为 non-login shell。
记住几个组合按键:
4.4、通配符与特殊符号
通配符(wildcard)是一个非常有用的功能。
bash中常见的特殊符号。理论上,你的文件名尽量不要使用到上述的字符。
5、数据流重定向
数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据传输到其他的地方,l例如文件或者是设备。这玩意儿在Linux的文本模式下面可重要的,尤其是如果我们想要将某些数据保存下来时,就更有用了。
5.1、什么是数据流重定向
Standard output (标准输出)和 Standard error (标准错误)都是默认输出到屏幕上面来的。
简单来说,标准输出指的是命令执行所回传的正确信息,而标准错误输出可理解为命令执行失败后,所回传的错误信息。
标准输入(stdin):代码为0,使用 < 或者 <<;
标准输出(stdout):代码为1,使用 > 或者 >>;
标准错误(stderr):代买为2,使用 2> 或者 2>>;
">" 表示以覆盖方式写入,">>"表示以追加方式写入。
将标准输出和错误输出写入不同文件:
find /home -name .bashrc > right.txt 2> error.txt
如果要将正确与错误写入相同文件:
find /home -name .bashrc > /dev/null 2>&1
/dev/null 垃圾桶黑洞设备与特殊写法,这个/dev/null 可以吃掉任何导向这个设备的信息。
Standard input(标准输入):将原本由键盘输入的数据改由文件的内容来替代。
cat > catfile < ~/abc.txt
5.2、命令执行的判断依据: “;” “&&” “||”
在某些情况下,我们想一次性输入多个命令去执行,有两个选择。
1、cmd; cmd #不考虑命令相关性的连续命令执行
如:sync; shutdown -h now
在命令与命令中利用分号(;)来隔开,这样一来,分号前的命令执行完后就会立刻接着执行后面的命令了。Linux下命令是由左往右走执行的。
2、$?(命令回传码)与 && 或 ||
若前一个命令执行的结果为正确,在Linux下面会回传一个 $?=0 的值。
5.3、双重定向
想要将数据流处理过程中将某段信息存下来,就可以利用 tee命令。
tee 命令会同时将数据流送与 文件 和 屏幕(screen)
6、管道命令(pipe)
管道命令使用 " | " 这个界定符号。
其实管道命令" | " 仅能处理经由前面一个命令传来的正确信息,也就是 Standard output的信息,对于 Standard error并没有直接处理的能力。
在每个管道后面接的第一个数据必定是”命令“,而且这个命令必须要能够接收 standard input 的数据才行,这样的命令才可以是”管道命令“。
6.1、选取命令:cut,grep
什么是选取命令,说穿了,就是讲一段数据经过分析后,取出我们所想要的,或者是经由分析关键字,去得我们所想要的那一行。
cut 命令
这个命令可以将一段信息的某一段”切“出来,处理的信息是以”行“为单位。
cut 主要的用途在于将同一行里面的数据进行分解,最常使用在分析一些数据或文字数据的时候。
grep 命令
grep 是分析一行信息,若当中有我们所需要的信息,就将该行拿出来。
grep 可以解析一行文字,去得关键字,若该行有存在
6.2、排序命令:sort,wc,uniq
sort 是很有趣的命令,它可以帮助我们进行排序,而且可以依据不同的数据类型来排序。
uniq,排序完成后,想将重复的数据仅列出一个显示。
wc,知道文件里面有多少行,多少字,多少多少字符。
重点回顾:
由于内核在内存中是受保护的块,因此我们必须要通过”Shell“将我们输入的命令与Kernel通信,好让Kernel可以控制硬件来正确无误地工作。
学习Shell的主要原因有:命令行界面的shell在各大distribution都一样;远程管理时命令行界面速度较快;shell是管理Linux系统非常重要的一环,因为Linux内很多控制都是以shell编写的。
系统合法的shell均写在/etc/shell文件中。
用户默认登陆取得的shell记录于/etc/passwd的最后一个字段。
bash的功能主要有命令编辑功能、命令与文件补全功能、命令别名设置功能、作业控制、前台、后台控制、程序化脚本、通配符。
type可以用来找到执行命令为何种类型,也可用于与which相同的功能。
变量就是以一组文字或符号等来替换一些设置或者是一串保留的数据。
变量主要有环境变量和自定义变量,或称为全局变量和局部变量。
使用 env(environment)与export可查看环境变量,其中export可以将自定义变量转换成环境变量。
set 可以查看目前bash环境下的所有变量。
$?也为变量,是前一个命令执行完毕后的回传码。在Linux回传码为0代表执行成功。
locale可用于查看语系数据。
可用read让用户由键盘输入变量的值。
ulimit 可用以限制用户使用系统的资源情况。
bash的配置文件主要分为 loginshell 与 non-login shell。 login shell 主要读取 /etc/profile 与 ~/.bash_profile,non-login shell 则仅读取 ~/.bashrc。
通配符主要有 * ? [ ]等。
数据流重定向通过 >、2>、< 之类的符号将输出的信息转到其他文件夹或设备去。
连续命令的执行可通过:&&,||等符号来处理。
管道命令的重点是它仅会处理 standard output,对于 standard error output 会予以忽略。管道命令必须要能偶接收来自前一个命令的数据成为 standard input继续处理才行。