终端、命令行、Bash、Shell 与进程理论梳理

📅 2026/7/21 8:33:24
终端、命令行、Bash、Shell 与进程理论梳理
目录一、是什么二、用来干什么三、关系四、内部原理与三大核心流程4.1 Bash 怎么找到你的应用程序4.2 程序是怎么跑起来的启动流程4.3 为什么退出终端 / 退出 Bash程序会停退出机制五、总结一、是什么术语本质通俗理解类比餐厅后厨终端Terminal一个应用程序软件也就是你屏幕上那个带光标、黑底白字的窗口。传菜窗口 / 工位。你在这个窗口递出指令结果也从这个窗口端出来。控制台Console历史上指物理的总控硬件键盘屏幕。如今在日常使用中几乎等同于终端命令行Command Line一种交互方式。你不是用鼠标点图标而是敲一行行文字指令。口头点餐。相对于对着图片指指点点这是纯文字的沟通方式。Shell壳一类软件统称。它负责接收你敲的文字翻译给操作系统内核听。“翻译官”这个职业。专门负责把人话翻译成机器能懂的操作。Bash一种具体的 Shell 实现。是目前 Linux/Mac 上最主流的翻译官软件品牌。具体的翻译官本人比如姓张的翻译官。和 Zsh、Fish 是平级关系二、用来干什么既然我们有图形界面鼠标点点点为什么还要用这些东西批量化与自动化鼠标改 1 万个文件名得累死但命令行一行 rename 指令一秒搞定还能写成脚本Shell Script定时自动运行。直触系统核心图形界面像隔着手套摸东西很多底层报错会被隐藏。命令行能看到最原始的错误日志拥有最高权限去修改系统配置文件。远程操控的必要手段服务器通常托管在千里之外的机房没有屏幕和鼠标。你只能通过 SSH 软件远程打开一个终端依靠命令行进行维护。三、关系完整祖孙链终端进程 → bash → my_app终端是个进程打开终端它会主动调用系统接口forkexec 拉起一个 shell默认 bashbash 成为终端进程的子进程。你在 bash 里执行 ./my_appbash 再 fork 一个子进程exec 替换成 my_app。fork 复制当前进程生成一个几乎一模一样的子进程父子进程代码、内存完全相同只是 PID 不同。 只复制不换程序。exec替换当前进程里运行的程序把进程原有代码、资源全部覆盖加载新程序运行。 只换程序不新建进程。四、内部原理与三大核心流程4.1 Bash 怎么找到你的应用程序当你敲下命令比如 my_app时Bash 不是立刻去硬盘搜而是按以下优先级查字典查别名Alias你是不是给命令起了小名比如 ll 代表 ls -l查内置命令Built-in是不是 cd、exit 这种 Bash 自带的亲儿子命令查哈希缓存Hash以前用过这命令吗如果记得绝对路径直接复用提速。查环境变量 PATH终极搜索如果以上都没命中Bash 才会从左到右遍历 $PATH 里的文件夹如 /usr/bin、/bin。内置命令不会 fork 子进程直接在bash自身进程里执行4.2 程序是怎么跑起来的启动流程找到应用程序后父子进程建立的核心是 Fork Exec 模型1. Fork分身Bash 调用fork()系统调用复制出一个完全一样的分身进程。此时内存中有两个进程Bash父原来的进程Bash子复制出来的分身它们拥有完全相同的代码、内存和环境变量唯一的区别是 PID。2. Exec变身分身进程调用exec()系统调用。exec()接收两个核心参数程序路径/usr/bin/python→ 告诉内核要加载哪个可执行文件参数数组[python, my_app.py, --host, 0.0.0.0, --port, 8000]→ 告诉新程序启动时的argv内容执行后的变化子进程的代码段被完全替换为 Python 解释器的代码参数数组被内核保存等待 Python 的main()函数接收3. 连接输入输出重定向子进程虽然代码变成了 Python但它的标准输入stdin、标准输出stdout文件描述符继承自父进程 Bash而 Bash 又继承自终端进程。因此操作系统将 Python 程序的标准输入连到键盘操作系统将 Python 程序的标准输出连到终端屏幕4. 最终效果Python 程序启动sys.argv中已有参数print()输出到屏幕input()等待键盘输入运行结束后通过exit()返回状态码给 Bash4.3 为什么退出终端 / 退出 Bash程序会停退出机制场景一本地关闭终端窗口终端爷爷关闭内核发送 SIGHUP挂断信号 给所有子孙。Bash父收到信号默认会转发给子进程应用程序。绝大多数程序收到 SIGHUP 会默认自杀。这就叫“关窗口程序停”。例外用 nohup 启动的程序会无视该信号或像 Nginx 那样主动“脱离”终端变为守护进程窗口关了它也在跑。场景二Docker 容器里退出 Bash特殊在 Docker 容器中Bash 通常是 PID 1法人代表。当你敲 exit 退出 Bash意味着 PID 1 进程终结。Linux 内核发现一个隔离空间容器的“老祖宗”死了会强制摧毁整个容器空间里面的应用程序哪怕还在跑也会被连根拔起。解决方法让应用程序本身成为 PID 1即 Dockerfile 的 CMD 直接写程序而不是写 /bin/bash。五、总结你双击终端图标(Terminal)↓ 启动 Shell 解释器(默认是 Bash)↓(你在 Bash 里敲命令)Bash 按优先级找程序Alias → Built-in → Hash缓存 → 遍历$PATH↓(找到 /usr/bin/my_app)Bash 调用 fork()克隆子进程 → 子进程 exec()变身为 my_app ↓ 终端--(输入输出)-- Bash(父)等待中--(父子关系)-- my_app(子)运行中