理解Shell:从命令到原理 一、什么是ShellShell是一个用C语言编写的程序它是用户使用Linux的桥梁。Shell既是一种命令语言你敲命令它执行又是一种程序设计语言可以写脚本。通俗地说你在Xshell里看到的那个黑底白字、等待你输入命令的界面就是Shell在等你。它的核心工作是接收你输入的命令 → 解析并传递给Linux内核 → 把执行结果返回给你。Shell脚本.sh文件就是将多条Shell命令按顺序写入一个文件然后批量执行实现自动化操作。二、Shell的类型Linux系统支持多种不同的Shell程序它们各有特点适用于不同的使用场景。Bash ShellBourne Again Shell是最常用的一种它是大多数Linux发行版的默认Shell。Bash在早期Bourne Shell的基础上增加了命令历史、Tab补全、别名等便利功能是目前Linux环境下事实上的标准。Bourne Shell/bin/sh是Unix系统上最早的Shell程序由Stephen Bourne开发。虽然功能比Bash简单但Bash完全兼容Bourne Shell的语法所以在脚本中经常可以看到 #!/bin/sh 的写法它同样可以被Bash正确执行。C Shell/bin/csh的语法风格类似于C语言适合习惯C语法的程序员使用。K Shell/bin/ksh则结合了Bourne Shell和C Shell的优点功能十分强大。重点Bash是大多数Linux系统的默认Shell。在脚本文件第一行写 #!/bin/bash就是告诉系统用Bash来执行这个脚本。查看当前用户默认的Shellcat /etc/passwd在输出的用户信息中第7个字段就是默认Shell的路径。三、Shell的父子关系父Shell当你登录系统或打开终端仿真器如Xshell时系统启动的那个Shell就是父Shell。子Shell在父Shell中再输入 /bin/bash 命令会创建一个新的Shell这个新Shell就是子Shell。可以这样理解父Shell是你的主窗口子Shell是在这个窗口里再开的一个子窗口。查看进程间的父子关系ps --forest这个命令会以树形结构显示进程能清楚看到哪个Shell是父、哪个是子。退出子Shellexit四、Shell的运行模式命令列表用分号 ; 将多个命令连接在一行Shell会依次执行它们cd / ; ls -l ; pwd进程列表子Shell将命令列表用括号括起来会生成一个子Shell来执行这些命令(cd / ; ls -l ; pwd)判断是否在子Shell中echo $BASH_SUBSHELL返回 0当前不在子Shell中返回 1 或更大的数字当前在子Shell中后台模式在命令末尾加上 命令会在后台运行不占用终端你可以继续输入其他命令sleep 60 查看后台任务jobs协程coproc协程可以在后台生成一个子Shell并执行命令实现同时做两件事的效果coproc sleep 10自定义协程名称注意花括号前后的空格和结尾的分号coproc My_Job { sleep 10; }五、内建命令与外部命令Linux中的命令可以分为两种类型内建命令和外部命令。这两者的本质区别在于它们是否属于Shell程序本身的组成部分。内建命令是已经和Shell编译成一体的命令它们作为Shell工具的组成部分存在不需要借助外部程序文件来运行。当你输入内建命令时Shell直接执行对应的操作不需要创建新的子进程。因此内建命令的执行速度更快效率也更高。常见的内建命令包括 cd切换目录、exit退出Shell、history查看历史命令和 alias创建别名等。外部命令则相反它们是存在于Shell之外的程序通常位于 /bin、/usr/bin、sbin 或 /usr/sbin 等目录中。当外部命令执行时Shell会通过衍生创建一个新的子进程来运行该程序。这个过程需要花费额外的时间和系统资源来设置新子进程的环境。例如ps 命令就是一个典型的外部命令。如何区分一个命令是内建还是外部 可以使用 type 命令来查看。如果输出中包含 is a shell builtin说明它是内建命令如果输出显示的是一个路径如 /bin/ls则说明它是外部命令。有些命令比较特殊同时存在内建和外部两种版本比如 echo 和 pwd。它们的内建版本由Shell直接提供外部版本则是独立的程序文件两者的实现细节可能略有不同。要查看一个命令的所有版本可以使用 type -a 命令而 which 命令则只显示外部命令的文件路径。如何区分type 命令名输出 xxx is a shell builtin → 内建命令输出 xxx is /bin/xxx → 外部命令有些命令既有内建版本也有外部版本如 echo、pwdtype -a echo # 查看所有版本which echo # 只显示外部命令的路径六、内建命令详解historyhistory 命令会显示你之前输入过的所有命令列表每个命令前面有一个编号。查看历史记录history历史记录存储在哪里内存中当前会话输入的命令用 history 可以看到文件中~/.bash_history隐藏文件存储的是上一次退出Shell时保存的命令重要特性当前会话的命令历史先存放在内存中只有当你退出Shell关闭终端时才会被写入到 ~/.bash_history 文件中。强制写入不退出Shell把当前历史写入文件history -a重新执行历史命令!! # 重复执行上一条命令!数字 # 执行历史列表中对应编号的命令如 !123七、内建命令详解aliasalias 命令可以为长命令创建别名减少输入量。查看当前所有别名alias -p常见别名如 ll ls -al、la ls -A。创建自己的别名alias li‘ls -li’之后输入 li 就等于输入 ls -li。注意别名仅在当前Shell会话中有效。关闭终端后别名会失效。要让别名永久生效需要将 alias 命令写入 ~/.bashrc 文件。删除别名unalias 别名名称查看历史命令列表查看历史文件中最后5条记录注意与 history 命令当前输出的差异。使用 !! 和 !编号 执行历史命令的效果执行强制写入后再次查看历史文件确认内容已更新。