理解Shell
一、什么是Shell
Shell是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。
简单来说,Shell是指一种应用程序,它提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Shell脚本(Shell Script)是为Shell编写的脚本程序,文件名通常以.sh结尾。
二、Shell的类型
Linux中常见的Shell种类:
| Shell类型 | 路径 | 说明 |
| Bourne Shell | /bin/sh | 最早的Shell |
| Bourne Again Shell | /bin/bash | 最常用,大多数Linux默认 |
| C Shell | /usr/bin/csh | C语言风格的Shell |
| K Shell | /usr/bin/ksh | 功能强大的Shell |
| Shell for Root | /sbin/sh | 根用户专用 |
查看当前使用的Shell
bash
echo $SHELL
# 输出:/bin/bash
查看系统所有可用Shell
bash
cat /etc/shells
脚本文件第一行的意义
bash
#!/bin/bash
#!是特殊表示符,后面跟解释此脚本的Shell路径
也可以换成其他解释器,如#!/usr/bin/python
查看用户默认Shell
bash
cat /etc/passwd
用户ID记录的第7个字段列出了默认的Shell程序。
启动其他Shell
bash
/bin/dash # 启动dash shell
exit # 退出当前shell
三、Shell的父子关系
3.1 什么是父Shell和子Shell
父Shell:用户登录虚拟控制台或启动终端仿真器时启动的默认交互式Shell
子Shell:在CLI提示符后输入/bin/bash命令时创建的新Shell
3.2 演示父子Shell关系
bash
# 查看当前Shell进程
ps --forest
# 输入多次bash创建多层子Shell
bash
bash
bash
# 此时输入 ps --forest 可以看到嵌套结构
# 查看进程关系
ps -f
# PID 是进程ID,PPID 是父进程ID
3.3 退出子Shell
bash
exit # 每次退出当前层Shell
四、Shell的运行模式
4.1 命令列表
在一行中用分号(;)依次执行多个命令:
bash
cd ~ ; ls ; pwd
4.2 进程列表
将命令列表放在括号中,会生成一个子Shell来执行:
bash
(cd ~ ; ls ; pwd)
4.3 检测子Shell
使用$BASH_SUBSHELL环境变量:
返回0:没有子Shell
返回1或更大:存在子Shell
bash
echo $BASH_SUBSHELL # 输出:0
(echo $BASH_SUBSHELL) # 输出:1
4.4 后台模式
在命令末尾加&,让命令在后台运行:
bash
sleep 60 &
# 输出:[1] 12345 (作业号与进程ID)
# 查看后台作业
jobs
# 查看进程
ps -f
注意:后台作业完成后会显示结束状态。
4.5 协程命令(coproc)
协程在后台生成一个子Shell并执行命令:
bash
# 基本用法
coproc sleep 10
# 自定义名称(扩展语法)
coproc My_Job { sleep 10; }
格式要求:
第一个花括号{和命令名之间必须有空格
命令必须以分号;结尾
分号和闭花括号}之间必须有空格
五、内建命令 vs 外部命令
5.1 外部命令
存在于Shell之外的程序,位于/bin、/usr/bin、/sbin等目录
执行时会创建子进程(称为衍生/forking)
例如:ps、ls、which
bash
which ps
# 输出:/bin/ps
type ps
# 输出:ps is /bin/ps
5.2 内建命令
与Shell编译为一体,属于Shell工具的一部分
不需要子进程执行,速度更快、效率更高
例如:cd、exit、history、alias
bash
type cd
# 输出:cd is a shell builtin
5.3 同时存在内建和外部版本的命令
bash
type -a echo
# 输出:
# echo is a shell builtin
# echo is /bin/echo
which echo
# 输出:/bin/echo (只显示外部命令)
六、history命令详解
history是内建命令,用于跟踪用户使用过的命令。
6.1 基本使用
bash
history
# 显示所有历史命令(带编号)
6.2 历史文件存储位置
命令历史记录保存在隐藏文件~/.bash_history中。
重要特性:历史记录先存放在内存中,当Shell退出时才写入历史文件。
6.3 验证内存与文件的区别
bash
# 查看历史文件末尾
tail ~/.bash_history
# 查看当前会话历史
history
# 两者内容不同(当前会话命令还未写入文件)
6.4 强制写入历史文件
bash
history -a # 强制将当前会话历史写入.bash_history
6.5 调用历史命令
bash
!! # 重新执行上一条命令
!123 # 执行历史中编号为123的命令
!ls # 执行最近一条以ls开头的命令
七、alias别名命令
alias是内建命令,允许为常用命令创建别名,减少输入量。
7.1 查看已有别名
bash
alias -p
# 显示所有已定义别名
7.2 创建别名
bash
alias li='ls -li'
alias ll='ls -al'
alias gs='git status'
7.3 删除别名
bash
unalias li
7.4 别名的作用范围
命令别名属于内部命令,仅在定义它的Shell进程中有效。退出当前Shell后,别名丢失(除非写入~/.bashrc)。
7.5 永久保存别名
bash
echo "alias li='ls -li'" >> ~/.bashrc
source ~/.bashrc
八、知识框架总结
理解Shell
│
├── Shell定义
│ └── 用户访问内核的桥梁(C语言程序)
│
├── Shell类型
│ ├── sh(Bourne Shell)
│ ├── bash(Bourne Again Shell)★ 默认
│ ├── csh、ksh、dash等
│ └── 查看:/etc/passwd 第7字段
│
├── 父子Shell关系
│ ├── 父Shell:登录时启动的默认Shell
│ ├── 子Shell:输入bash命令创建
│ ├── ps --forest查看嵌套结构
│ └── exit逐层退出
│
├── 运行模式
│ ├── 命令列表(;分号分隔)
│ ├── 进程列表(括号中执行→生成子Shell)
│ ├── 后台模式(&符号)
│ └── 协程(coproc)
│
└── 命令分类
├── 外部命令
│ ├── 独立程序文件(/bin、/usr/bin)
│ ├── 执行需fork子进程
│ └── which / type 查看
└── 内建命令
├── 与Shell编译在一起
├── 速度快,无需子进程
├── cd、exit、history、alias
├── history:-a强制写入,!!重复执行
└── alias:创建别名,仅当前Shell有效










openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)