%% # 纲要 > 主干纲要、Hint/线索/路标 # Q&A #### 已明确 #### 待明确 > 当下仍存有的疑惑 **❓<font color="#c0504d"> 有什么问题?</font>** # Buffer ## 闪念 > sudden idea ## 候选资料 > Read it later %% # 关于 shell > shell 俗称"壳",表示其"区别于内核",是用户与操作系统内核进行交互的桥梁。 shell 是一个**命令行解释器**,提供了一个**命令行界面**,同时也是一种**脚本语言**。 - **==命令行解释器== (command line interpreter, CLI)** - **==命令行界面==(command line interface, CLI)**: - **==脚本语言==** shell 提供了 "shell 命令行" 作为用户与操作系统进行交互的接口,其核心功能是作为一个**命令行解释器**,负责**解释用户在命令行界面输入的命令**,**并在内核中执行相应的操作**。 shell 同时提供了一个**命令行界面**,**供用户输入命令、显示命令执行的输出**等。命令行界面只允许输入/显示文本。 shell 也作为一种脚本语言,提供了一个**编程环境 (相关语句和语法)**,支持**脚本编写**。 ### shell 的实现 Linux 中有许多种 **shell 实现**,包括: - **==sh==**(Bourne Shell): - Unix 系统最初的**标准 Shell** (即最原始版本),在现代系统上通常是**指向系统默认 shell 的一个符号链接**。 - **==Bash==**(Bourne Again Shell): - **最常见的 Linux Shell**,是许多 Linux 发行版的**默认 Shell**。<br>bash 是为 GNU 项目所编写的 Unix Shell,基于 Bourne Shell 的同时吸收了 C shell 和 Korn shell 的一些特性,其完全兼容 Bourne shell,用 Bourne shell 编写的脚本不加修改就可以在 bash 中执行。 - **zsh (Z Shell)**: - 类似于 Bash,但提供了额外的功能,如更好的自动完成和主题支持。 - **csh 和 tcsh**: - 以 C 语言风格的语法而闻名。 > ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-95223BF2F568ACDC74B9858A595E0A8B.png|581]] <br> ### shell 程序 **shell 的可执行程序**默认都位于 `/bin` 目录下,例如 `/bin/sh` 与 `/bin/bash`: - `/bin/sh`: 在早期 Unix 系统上即是 Bourna shell,而 **Linux 系统上**通常都将 `sh` 作为一个**软连接**,链接到 **系统默认 shell** - **Debian、Ubuntu 系统中的默认 shell 是 dash**; - CentOS 系统中的默认 shell 是 bash。 - `/bin/bash`:**Bash Shell 的可执行程序**。 > [!NOTE] > > 查看 sh 路径:可通过 `which sh` 查看 `sh` 所在路径,再通过例如 `ls -l /usr/bin/sh` 的指令查看`sh`的指向。 > > ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-AA529CBF75826FB44C3270F40951A037.png]] > > ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-7628A81662180709FD7811E565318810.png]] > > <br> ## 命令行提示符 shell 命令行界面下显示了"**命令行提示符**" (prompt),即位于命令输入行头部位置的一段文本。 命令行提示符提供了:**当前用户名**、**系统的主机名**、**当前工作目录`pwd`**。 ```shell # 普通模式下的命令行提示符: username@hostname:pwd$ # root模式下的命令行提示符: root@hostname:pwd# ``` 结尾的 `
是一个普通用户的提示符结束符;对于 root 用户则通常是 `#`。 ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-FEACAA99E235F2AB07C694AE8D63F89D.png]] 在 Bash 中,提示符是通过环境变量 `PS1` 定义的。 可以编辑 `~/.bashrc` 或 `~/.bash_profile` 文件来改变 `PS1` 的值,从而定制提示符。例如: ```shell export PS1='\u@\h:\w\$ ' ``` 其中 `\u` 表示用户名,`\h` 表示主机名,`\w` 表示当前工作目录,`\
为结束符。 <br><br> ## 运行/启动 shell > 术语:"**shell 会话**"" == "**shell 进程**" == "**shell 实例**" 用户在登录到系统时,会启动一个 "**登录式 shell**",**具体启动的 shell 程序 (bash、dash 等) 取决于用户账户配置文件 `/etc/passwd` 中该用户配置的最后一个字段**。 ### 默认 Shell - **默认的交互式 shell**(default interactive shell)也即 **==登录 shell==** - 用户登录终端时默认启动的具体 shell 程序(bash/dash 等)由**用户账户配置文件 `/etc/passwd` 中该用户配置的最后一个字段指定**。 - **默认的系统 shell** (default system shell):即 `sh` (`/bin/sh`) ,用于那些 **==需要在启动时使用的系统 shell 脚本==**。 ### 当前 shell 在 shell 会话 (命令行界面) 中,环境变量 `$0` 为 **==当前 shell 的名称==**。可通过 `echo $0` 命令查看 > 如果在 shell 脚本中查看该环境变量,则显示的是"**该 shell 脚本**"的名称。 ## shell 的命令搜索目录 环境变量 `PATH` 定义了 shell 查找 **可执行文件** 的搜索目录列表。 当在命令行中输入一个命令时,shell 会**按照 `PATH` 环境变量中罗列的顺序,依次从这些目录中搜索可执行命令**。 > 例如,如果 `PATH` 的值为 `/usr/local/bin:/usr/bin:/bin`,shell 首先会在 `/usr/local/bin` 中查找命令,如果没找到,接着在 `/usr/bin` 查找,以此类推。 #### PATH 环境变量 环境变量 `PATH` 是一个包含**由冒号 (`:`) 分隔**的**目录路径的字符串**。 每个路径指向一个文件系统中的目录,Shell 会在这些目录中**查找可执行文件**。 - **查看当前 PATH**:使用 `echo $PATH` 命令可查看环境变量 `PATH` 的值。 - **修改 PATH**: - **临时修改**:使用 `export PATH=$PATH:/new/path` 命令临时修改,该更改**仅对当前 shell 会话有效**。*。 - **永久修改**:要永久修改 `PATH`,需要在系统或用户的登录配置文件或 shell 配置文件中添加上述 export 命令,并重新加载配置文件触发生效。发生效。 <br><br> # 关于 bash Bash(Bourne Again SHell)是**最常见的一种 Unix Shell**。 bash 是为**GNU 项目所编写的 Unix Shell**,作为原始 Bourne shell 的自由软件替代品。 bash 在基于 Bourne Shell 的同时吸收了 C shell 和 Korn shell 的一些特性,其**完全兼容 Bourne shell**,用 Bourne shell 编写的脚本不加修改就可以在 bash 中执行。 ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-5FE6286C1D7DB5C82755E0847A0ED14F.png]] Bash 的功能特性: - **命令历史和补全**:Bash 会输入的历史命令,可以通过上下箭头键浏览历史记录,支持反向搜索历史命令 - **命令补全**:通过 `Tab` 键可以自动补全命令和文件名。 - **脚本编写**:Bash 同时是一种流行的脚本语言,支持编写脚本以自动化复杂的任务。 Bash 脚本支持变量、条件判断、循环控制结构、函数等编程特性。 - **命令别名**:可以为常用的长命令创建简短的别名。 - **作业控制**:支持将命令放入后台执行,以及将后台命令带回前台。 - **环境配置**:用户可以通过编辑 `~/.bashrc`、`~/.bash_profile` 等配置文件来定制自己的 bash shell 环境。 - **兼容性**:保持对旧版 Bourne shell 脚本的兼容性,同时扩展了其功能。 <br> ## `bash` 命令 `bash [options] [command_string | file] ` **启动新的 bash 会话**(进程) - `-c`:将第一个非选项的**参数" `command_string`" 作为需要执行的命令**,在新启动的 bash 中执行。 - 如果 `command_string` 之后跟有参数,则**第一项参数**将作为**bash 的名称赋给环境变量 `$0`**。<br>其余参数作为位置参数传递给 `command_string` 命令。 - `-i`:启动一个交互式 shell 会话。(可用于在脚本中使用`bash -i`启动交互式 shell) - `-l`, `--login`:以 "**登录 shell**" 的方式启动 Bash,会使得 Bash 读取和执行**登录配置文件**。 - `-s`:从标准输入读取命令。通常与管道配合使用,例如:`echo 'echo Hello World' | bash -s` - `-e`:如果**任何命令返回非零退出状态**,则**立即退出 shell**。通常用于脚本中,以确保脚本在出错时停止执行。 - `-x`:在执行命令前打印命令及参数。通常用于调试,例如:`bash -x script.sh` - `-v`:在读取输入行时打印 shell 输入行,通常用于脚本调试。 - `--norc`:作为交互式非登录 shell 启动 bash 时,**不读取 `~/.bashrc` 配置文件**。 - `--noprofile`: 作为登录 shell 启动 bash 时,不读取 `/etc/profile` 和 `~/.bash_profile` 等配置文件。 ```shell bash -c 'echo Hello World' # 执行命令 bash my_script.sh # 执行脚本 bash -l myscript.sh # 以"登录shell"的方式启动bash, 并执行该脚本 bash -e myscript.sh # 如果脚本中任何命令出错(返回非零退出状态码), 则立即退出bash.停止执行 bash --norc myscript.hsh # 启动bash时不读取 `~/.bashrc` 配置文件. ``` <br><br><br> # shell 命令 ## shell 内部命令与外部命令 shell 命令可以分为内部命令和外部命令。 - ==**内部命令==(Build-in commands)**:内部命令是**shell 本身的一部分**,与 shell 编译成一体,**直接由 shell 程序执行**,<br>**无需调用外部程序文**件,也**不需要创建子进程来执行**。 - 例如 `cd`,`echo`,`exit`,`history` , `type`,`set`,`unset`,`alias` 等。 - **==外部命令==(文件系统命令)**:外部命令不属于 shell 的内置部分,而是存放在文件系统上的**可执行文件**。<br>当执行外部命令时,会从 shell 中创建一个**新的子进程**。 - 例如 `ps`,`ls`,`grep`,`awk`,`cat` 等。 - shell **仅在 `PATH` 环境变量指定的路径**中搜索外部命令。 - (通常存放在 `/usr/bin`,`/usr/sbin` 等目录下,也可以在其它任何位置) #### 区分内部命令与外部命令 - 通过 `help` 可查看**内部命令**的说明。 - 通过 `type` 可查看**命令的类型**,对于外部命令会显示其对应的文件路径。 - 通过 `which` 可查看**外部命令**对应的文件路径。 有些命令有内、外部多种实现。通过 `type -a` 可查看命令的两种实现, 例如 `echo`、`pwd`、`set` 等。 ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-3002E2376CE2B443EE22C2DDD86AB9A3.png]] 对于有多种实现的命令,如果想使用其**外部命令实现**,直接**指明对应的文件即可**。 例如,要使用外部命令 `pwd`,可以输入 `/usr/bin/pwd`。 > [!NOTE] > > 通过 `help` 命令可一览所有 shell 内置命令 > > ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-A0B441A63D6E9B231730AA9C71E6F740.png|629]] > > <br> ## 命令行选项与参数 shell 命令中的选项(option)与参数(arguments)是运行命令或脚本时**传递的不同类型的输入值**: - **==选项==(option)**:通常用来**调整、控制命令行程序的行为**,启用或禁用某些功能。选项的形式包括: - 以单个连字符 `-` 起始的短选项(例如`-l`,`-r` 等) - 以两个连字符 `--` 起始的长选项(例如`--version`,`--all` 等) - 示例:`ls -l` - **==参数==(arguments)**:参数是**传递给命令的实际数据或指令**,用于提供执行命令所需的数据,例如文件名、数值等数据。示例:`cp source.txt destination.txt` **选项后面可以带有参数**,即该选项所需的参数值。例如:`./testing.sh -a test1 -b -c -d test2` > [!NOTE] > 命令行参数是在命令/脚本名之后出现的各个单词,其中,以连字符(`-`)或双连字符(`--`)起始的参数因其能够改变命令的行为,称作命令行选项。所以,**命令行选项是一种特殊形式的命令行参数**。 > 常用 Linux 命令行选项: > > ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-3F913F966093E60FED0D6AE5EABF3FA9.png|643]] <br><br> ## 退出状态码 在 Shell 中,命令的退出状态码(或退出码)是一个用于**表示命令执行成功或失败**的数字。 shell 中运行的每个命令都使用**退出状态码**来告诉 shell 自己已运行完毕,并告知命令执行成功或失败。 退出状态码是一个 `[0, 255]` 之间的整数值,**在命令结束运行时**由其传给 shell。 在 Unix 和 Linux 系统中,状态码遵循特定的约定: - **0 表示成功**:如果命令执行成功且没有发生错误,则**退出状态码通常为 0**。 - **非 0 表示失败**:如果命令执行失败或出现错误,退出状态码是一个非 0 值。不同的值可以表示不同类型的错误。 可以使用特殊变量 `$?` 来查看**最后一个已执行命令**的退出状态码。**对于需要进行检查的命令,必须在其运行完毕后立刻查看或使用`$?`变量**。例如: ```shell $ somecommand $ echo $? ``` 对于 shell 脚本而言,默认会**以脚本中的最后一个命令的退出状态码**退出。 `exit <num>` 命令允许结束在脚本结束时指定一个退出状态码,也可以使用一个变量作为 exit 命令的参数。 > 常用状态码: > ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-C52445C1F08C96E99E3AA401A7FD260C.png|511]] <br><br><br> # shell 作业 在 Shell 中,**"作业"(Job)** 是指**由 shell 管理的在 "前台或后台" 运行的命令或进程**(**==由当前 shell 启动的==**) shell 作业包括两种: - **前台作业**:始终占用当前终端直至被完成或停止的作业,该期间用户不能与 shell 交互,直至作业结束。 - 一个 shell 会话中**一次只能有一个前台作业**,它占据终端直接与用户交互,没有作业号。 - **后台作业**:以后台模式 (`&`) 从当前 shell 中启动的作业,作为独立进程在后台运行。 - 每个 "后台作业" 都会被 shell 唯一地分配有一个**作业号**(从 1 起)。 > [!caution] **后台作业与终端绑定**,**==当终端会话退出时,所有后台进程也会随之退出==**。 > > 原因:终端被注销或退出时,会发送 `SIGHUP` 信号给其关联的所有子进程(包括后台进程)。 > > 如要分离后台进程与终端的关联,需使用 `nohup` 搭配 `&`:`nohup command [args...] &` > <br> ### shell 作业控制 Shell 提供了作业控制的功能,例如: - `jobs`:**列出当前会话中的所有作业及其状态**(运行中、已停止等)。 - `fg [job]`:**以前台模式运行后台作业**,即将后台作业带到前台来继续执行。 - `bg [job]` :**以后台模式重启被停止/暂停(Stopped)的作业**。即该作业将继续以后台模式运行。 - `kill`:发送信号给作业,通常用于终止作业。 参见[[02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令|Linux-进程相关命令]] <br> ### 后台模式 Linux 中支持 **在后台启动运行一个进程**, shell 会立即**返回命令行提示符**,允许用户继续执行其他命令,而后台作业则在后台运行。 以 "后台模式" 运行一个进程,只需在命令后**添加 `&` 符号**,该进程将作为一个 **==独立进程==运行在后台。** 当进程被置入后台时,会打印 `[n] PID` 格式的信息: **后台作业号 `n`**,以及**后台作业的进程 PID**。 ![[_attachment/02-开发笔记/11-Linux/shell 相关/shell 基本说明.assets/IMG-shell 基本说明-62C5002533D41E34AD089406EB43560F.png|405]] 当后台进程结束时,终端上会显示如下形式的一条消息: `[1]+ Done ./backgroundscript.sh` 其指明了作业号、作业状态(Done)、启动该作业的命令(去除了&)。 > [!NOTE] 后台作业结束信息可能会 "**直到下次执行能让 shell 生成命令行提示符的操作(如按下 Enter 键)时**" 才显示。 > [!caution] **后台进程运行时,==默认仍会占用当前 shell 终端显示器==来显示 STDOUT 和 STDERR 消息。** <br><br> # 参考资料 # Footnotes