接上一篇文章Linux shell编程(一):基本命令行
二、Linux shell基础
2.1 关于shell
前面讲过,shell也是一个程序,经常说的shell进程就是正在运行的shell程序(进程就是正在运行中的程序)。
2.1.1 父shell进程与子shell进程
当我们打开一个终端时,启动的shell就是一个父shell,在这个终端执行 bash
命令,会启动一个子shell,如下图:
第一次使用 ps -f 的时候,显示出了两个进程。其中一个进程的进程ID(PID)是 7264,运行的是bash shell程序。另一个进程(进程ID为 7311 )对应的是命令 ps -f 命令。
输入命令 bash 之后,一个子shell就出现了。第二个 ps -f 是在子shell中执行的。可以从显示结果中看到有两个bash shell程序在运行。第一个bash shell程序,也就是父shell进程,其原始进程ID是 7264。第二个bash shell程序,即子shell进程,其PID是 7312 。注意,子shell的父进程ID (PPID)是 7264 ,指明了这个父shell进程就是该子shell的父进程。
使用 ps --forest
命令,可以以树的形式显示进程间的父子关系,下:
2.1.2 关于子shell
子shell就是在一个shell中又开了一个shell。
生了另一个子shell来执行命令。因此数字 2 表明的就是这个子shell。
在shell脚本中,经常使用子shell进行多进程处理。但是子shell会产生不小的开销,明显拖慢处理速度,所以不能大量的使用子shell。但在交互式的CLI shell会话中,它并非真正的多进程处理,因为终端控制着子shell的I/O,即只有一个打印窗口。
常见的子shell用法有进程列表、后台模式、协程和管道。
进程列表
进程列表是用括号包起来的一组命令(命令列表)。
例如: pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls
是一组命令列表, (pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls)
是进程列表。他们之间的区别是进程列表会创建一个子shell并在子shell中执行命令,而命令列表是在父shell中直接执行命令,如下图:
执行命令 ls ; pwd ; ps --forest
时,显示 ps
命令是在父bash shell中执行的,而执行命令 (ls ; pwd ; ps --forest)
时,显示 ps
命令是在父bash shell中的子bash shell中执行的。
后台模式
在后台模式中运行命令可以在处理命令的同时让出CLI(打印窗口),以供其他命令使用,要想将命令置入后台模式,在命令末尾加上字符 &
即可。
例如 sleep
命令,当我们输入 sleep 10
时,会话会休眠10秒,此时此会话不能做其他事情,10秒过后才会返回命令提示符,但执行命令 sleep 10&
时,会话会立即返回命令提示符。
jobs
命令可以显示后台作业的信息,如下:
其中,方括号中是作业号,当前状态Running,以及对应命令,-l
参数可以显示作业的进程ID。
协程
协程可以同时做两件事。它在后台生成一个子shell,并在这个子shell中执行命令。
使用 coproc
命令创建协程,参数为要在子shell中执行的命令,如下:
其中,COPROC
是协程的名字,可以自定义这个名字,如下:
注意:花括号里面的命令必须要以 “;” 结尾,而且花括号和里面的命令之间要有空格间隔。
管道
管道被放在命令之间,将一个命令的输出重定向到另一个命令中。管道后面的命令会放在一个子shell中执行。
2.2 外部命令与內建命令
2.2.1 外部命令
外部命令,也称为文件系统命令,是存在于bash shell之外的程序。它们并不是shell程序的一部分。外部命令程序通常位于/bin、/usr/bin、/sbin或/usr/sbin中。
外部命令执行时,会创建出一个子进程。这种操作被称为衍生。
2.2.2 內建命令
内建命令和外部命令的区别在于前者不需要使用子进程来执行。它们已经和shell编译成了一
体,作为shell工具的组成部分存在。不需要借助外部程序文件来运行。
可以用 type
命令查看某个命令是否是内建的。有些命令有多种实现。例如 echo
和 pwd
既有内建命令也有外部命令。使用 type -a
可以查看命令的不同实现,如下:
历史命令列表-history
history是一个內建命令,它可以查看最近用过的命令列表,默认情况下history只展示最近的1000条命令,可以修改环境变量 HISTSIZE
来设置展示的命令条数。
输入 !!
然后按回车,可以重新执行刚刚用过的那条命令,输入 ![命令编号]
可以执行任意历史命令,如下:
命令历史记录被保存在隐藏文件.bash_history中,它位于用户的主目录中。
这里要注意的是,bash命令的历史记录是先存放在内存中,当shell退出时才被写入到历史文件中,可以使用 history -a
命令,在退出shell会话之前强制将命令历史记录写入.bash_history文件。
但其他已经打开的终端不会更新命令历史列表,因为.bash_history文件是在终端打开时才会被读取一次,可以使用 history -n
命令强制重新读取.bash_history文件。
命令别名-alias
alias也是一个內建命令,它可以为常用的命令(及其参数)创建另一个名称,从而减少输入量。
使用 alias -p
可以查看已有的命令别名。
使用 alias 别名=‘命令’
可以为命令创建别名,但这样只是在当前shell有效,可以将创建别名的语句写进用户目录下的 .bashrc
中,可以让别名在不同的子shell中都有效。
可以查看 .bashrc
文件中已经有的命令别名,如下: