一、什么是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/cshC语言风格的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有效

Logo

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

更多推荐