Linux Shell 完全入门指南:从概念到实战操作
一、什么是ShellShell是一个用 C 语言编写的程序它是用户使用 Linux 的桥梁。Shell 既是一种命令语言又是一种程序设计语言编程语言。Shell 是指一种应用程序这个应用程序提供了一个界面用户通过这个界面访问操作系统内核的服务。Shell 脚本Shell Script是一种为 Shell 编写的脚本程序文件名通常以.sh结尾。bash#!/bin/bash # 这是脚本文件的第一行指定此脚本使用 /bin/bash 来解释执行 # #! 是特殊表示符后面跟的是解释此脚本的 shell 的路径二、Shell的类型Linux 的 Shell 种类众多常见的有Shell 类型路径说明Bourne Shell/usr/bin/sh 或 /bin/sh最初的 ShellBourne Again Shell/bin/bash最常用大多数 Linux 默认C Shell/usr/bin/cshC 语言风格的 ShellK Shell/usr/bin/kshKorn ShellShell for Root/sbin/sh根用户专用Bash ShellBourne Again Shell在日常工作中被广泛使用同时Bash 也是大多数 Linux 系统默认的 Shell。在一般情况下人们并不区分 Bourne Shell 和 Bourne Again Shell所以像#!/bin/sh它同样也可以改为#!/bin/bash。三、Shell的父子关系3.1 父 Shell用于登录某个虚拟控制台终端或在 GUI 中运行终端仿真器时所启动的默认交互 Shell是一个父 Shell。3.2 子 Shell在 CLI 提示符后输入/bin/bash命令或其他等效的bash命令时会创建一个新的 Shell 程序这个 Shell 程序被称为子 Shellchild Shell。使用ps --forest命令可以展示子 Shell 间的嵌套结构PID进程 IDPPID父进程 ID3.3 实际操作bash# 查看当前 Shell 层级返回 0 表示父 Shell [rootlocalhost ~]# echo $BASH_SUBSHELL 0 # 进入子 Shell [rootlocalhost ~]# bash [rootlocalhost ~]# echo $BASH_SUBSHELL 1 # 再进入一层子 Shell [rootlocalhost ~]# bash [rootlocalhost ~]# echo $BASH_SUBSHELL 2 # 查看进程树 [rootlocalhost ~]# ps --forest PID TTY TIME CMD 1234 pts/0 00:00:00 bash 5678 pts/0 00:00:00 \_ bash 9012 pts/0 00:00:00 \_ bash 3456 pts/0 00:00:00 \_ ps # 使用 exit 逐层退出子 Shell [rootlocalhost ~]# exit [rootlocalhost ~]# exit [rootlocalhost ~]# echo $BASH_SUBSHELL 0四、Shell的运行模式4.1 命令列表在命令之间加入分号;可以在一行中指定 Shell 要依次运行的一系列命令。bash[rootlocalhost ~]# cd /home; ls -l; pwd total 4 drwx------. 2 user user 4096 Jul 6 10:00 user /home4.2 进程列表进程列表是一种命令分组方式。将命令列表包含在括号里会生成一个子 Shell来执行对应的命令。bash# 进程列表示例会生成子 Shell [rootlocalhost ~]# (cd /home; ls -l; pwd) total 4 drwx------. 2 user user 4096 Jul 6 10:00 user /home # 检查是否生成了子 Shell [rootlocalhost ~]# echo $BASH_SUBSHELL 0 [rootlocalhost ~]# (echo $BASH_SUBSHELL) 14.3 后台模式在命令末尾加上字符可以将命令置入后台模式在处理命令的同时让出 CLI 以供他用。bash# 将 sleep 命令放入后台 [rootlocalhost ~]# sleep 60 [1] 4567 # 查看后台作业 [rootlocalhost ~]# jobs [1] Running sleep 60 # 查看进程 [rootlocalhost ~]# ps PID TTY TIME CMD 1234 pts/0 00:00:00 bash 4567 pts/0 00:00:00 sleep 4568 pts/0 00:00:00 ps4.4 协程命令coproccoproc命令可以同时做两件事它在后台生成一个子 Shell并在这个子 Shell 中执行命令。bash# 默认名称 COPROC [rootlocalhost ~]# coproc sleep 10 [1] 5678 # 自定义名称扩展语法 # 注意第一个花括号 { 和命令名之间必须有空格 # 命令必须以分号 ; 结尾 # 分号和闭花括号 } 之间也必须有一个空格 [rootlocalhost ~]# coproc My_Job { sleep 15; } [2] 6789五、内建命令 vs 外部命令5.1 外部命令存在于 bash Shell之外的程序通常位于/bin、/usr/bin、/sbin或/usr/sbin中执行时会创建子进程这个过程称为衍生forkingbash# 查看外部命令的位置 [rootlocalhost ~]# which ps /usr/bin/ps # 查看命令类型 [rootlocalhost ~]# type ps ps is /usr/bin/ps5.2 内建命令已经和 Shell编译成了一体不需要使用子进程来执行执行速度更快效率更高bash[rootlocalhost ~]# type cd cd is a shell builtin [rootlocalhost ~]# type exit exit is a shell builtin5.3 同时存在内建和外部实现的命令echo和pwd既有内建命令也有外部命令。bash# 查看命令的所有实现 [rootlocalhost ~]# type -a echo echo is a shell builtin echo is /usr/bin/echo # which 只显示外部命令文件 [rootlocalhost ~]# which echo /usr/bin/echo六、内建命令 history 详解history命令会跟踪你使用过的命令你可以唤回这些命令并重新使用。6.1 配置文件位置命令历史记录被保存在隐藏文件.bash_history中位于用户的主目录。bash[rootlocalhost ~]# ls -la ~/.bash_history -rw-------. 1 root root 1024 Jul 6 10:00 /root/.bash_history6.2 内存与文件的关系重要理解bash 命令的历史记录先存放在内存中当 Shell退出时当前终端窗口关闭时才被写入到.bash_history文件中。6.3 实际操作验证bash# 1. 查看当前会话的历史命令内存中的 [rootlocalhost ~]# history 1 ls 2 cd /home 3 pwd 4 echo Hello # 2. 查看 .bash_history 文件上次会话保存的 [rootlocalhost ~]# tail -5 ~/.bash_history ls cd /home pwd exit # 3. 对比差异 # 可以发现.bash_history 的末尾是上次退出的命令 # 而 history 的末尾是当前会话实时输入的命令6.4 强制写入 -a 选项在退出 Shell 会话之前可以使用-a选项将当前会话的历史记录强制写入.bash_history文件。bash# 强制将当前会话的历史记录写入文件 [rootlocalhost ~]# history -a # 验证写入后 .bash_history 与 history 一致 [rootlocalhost ~]# tail -5 ~/.bash_history6.5 快速调用历史命令bash# 执行上一条命令 [rootlocalhost ~]# !! pwd /home # 执行 history 中编号为 120 的命令 [rootlocalhost ~]# !120 ls -la total 48 dr-xr-x---. 5 root root 4096 Jul 6 10:00 . dr-xr-xr-x. 17 root root 4096 Jul 6 09:00 ..6.6 history 完整练习bash# 步骤 1查看当前历史记录 [rootlocalhost ~]# history # 步骤 2输入几条新命令 [rootlocalhost ~]# ls -la [rootlocalhost ~]# pwd [rootlocalhost ~]# echo Hello Shell # 步骤 3再次查看 history确认新命令已记录 [rootlocalhost ~]# history # 步骤 4查看 .bash_history 文件可能还没有这些命令 [rootlocalhost ~]# tail -3 ~/.bash_history # 步骤 5强制写入 [rootlocalhost ~]# history -a # 步骤 6再次查看 .bash_history确认已同步 [rootlocalhost ~]# tail -5 ~/.bash_history # 步骤 7使用 !! 执行上一条命令 [rootlocalhost ~]# !! # 步骤 8使用 !编号 执行指定命令 [rootlocalhost ~]# !102 # 假设 102 是某条历史命令的编号七、内建命令 alias 详解alias命令允许你为常用的命令及其参数创建另一个名称从而减轻代码输入量。7.1 查看已有别名bash# 查看所有已设置的别名 [rootlocalhost ~]# alias -p alias cpcp -i alias l.ls -d .* --colorauto alias llls -l --colorauto alias lsls --colorauto alias mvmv -i alias rmrm -i--color表示终端支持彩色模式的列表。7.2 验证别名效果bash# ll 和 ls -al 显示结果是一样的 [rootlocalhost ~]# ll total 48 dr-xr-x---. 5 root root 4096 Jul 6 10:00 . [rootlocalhost ~]# ls -al total 48 dr-xr-x---. 5 root root 4096 Jul 6 10:00 .7.3 创建自定义别名bash# 创建别名 [rootlocalhost ~]# alias lils -li # 使用别名 [rootlocalhost ~]# li total 48 1234567 dr-xr-x---. 5 root root 4096 Jul 6 10:00 . # 查看所有别名包括自定义的 [rootlocalhost ~]# alias -p alias lils -li ...7.4 别名的作用范围重要理解命令别名属于内部命令一个别名仅在它所被定义的Shell 进程中才有效。bash# 在当前 Shell 中定义别名 [rootlocalhost ~]# alias mylsls -l # 进入子 Shell [rootlocalhost ~]# bash # 子 Shell 中无法使用该别名 [rootlocalhost ~]# myls -bash: myls: command not found # 退出子 Shell [rootlocalhost ~]# exit # 回到父 Shell别名仍然有效 [rootlocalhost ~]# myls total 48 dr-xr-x---. 5 root root 4096 Jul 6 10:00 .7.5 alias 完整练习bash# 步骤 1查看系统默认别名 [rootlocalhost ~]# alias -p # 步骤 2创建自定义别名 [rootlocalhost ~]# alias clsclear [rootlocalhost ~]# alias lals -a [rootlocalhost ~]# alias llals -la # 步骤 3测试自定义别名 [rootlocalhost ~]# cls [rootlocalhost ~]# la . .. .bash_history .bashrc [rootlocalhost ~]# lla total 48 dr-xr-x---. 5 root root 4096 Jul 6 10:00 . dr-xr-xr-x. 17 root root 4096 Jul 6 09:00 .. # 步骤 4查看所有别名确认 [rootlocalhost ~]# alias -p # 步骤 5测试别名仅在当前 Shell 有效 [rootlocalhost ~]# bash [rootlocalhost ~]# la -bash: la: command not found [rootlocalhost ~]# exit # 步骤 6删除别名使用 unalias [rootlocalhost ~]# unalias la [rootlocalhost ~]# la -bash: la: command not found八、知识框架体系总结Shell 知识体系思维导图text┌─────────────────────────────────────────────────────────────┐ │ SHELL │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 一、Shell 类型 │ │ ├── Bourne Shell/bin/sh │ │ ├── Bash Shell/bin/bash← 最常用默认 │ │ ├── C Shell/bin/csh │ │ ├── K Shell/bin/ksh │ │ └── Shell for Root/sbin/sh │ │ │ │ 二、Shell 父子关系 │ │ ├── 父 Shell登录时启动的默认交互 Shell │ │ ├── 子 Shell输入 bash 命令创建 │ │ ├── 查看命令ps --forest │ │ └── 退出命令exit │ │ │ │ 三、Shell 运行模式 │ │ ├── 命令列表使用分号;依次执行 │ │ ├── 进程列表使用括号()在子 Shell 中执行 │ │ ├── 后台模式使用 符号 │ │ └── 协程模式使用 coproc 命令 │ │ │ │ 四、Shell 命令分类 │ │ ├── 外部命令位于 /bin、/usr/bin 等衍生子进程 │ │ └── 内建命令已和 Shell 编译为一体速度快 │ │ │ │ 五、内建命令详解 │ │ ├── history命令历史-a 强制写入 │ │ └── alias命令别名仅在当前 Shell 有效 │ │ │ └─────────────────────────────────────────────────────────────┘九、常用命令速查表----------------------------------------------------------------------------------------------------- | 命令 | 用途 | 常用参数 | ----------------------------------------------------------------------------------------------------- | bash | 启动子 Shell | 无参数进入子 Shell | | exit | 退出当前 Shell | 无参数 | | ps --forest | 查看进程树结构 | --forest 显示树形结构 | | echo $BASH_SUBSHELL | 检查子 Shell 层级 | 返回 0 表示父 Shell | | jobs | 查看后台作业 | 无参数 | | history | 查看命令历史 | -a 强制写入-c 清空历史 | | !! | 执行上一条命令 | 无参数 | | !编号 | 执行指定编号的历史命令 | 编号从 history 中获取 | | alias -p | 查看所有别名 | -p 显示所有别名 | | alias 别名命令 | 创建别名 | 例alias llls -al | | unalias 别名 | 删除别名 | 例unalias ll | | which 命令 | 查看外部命令位置 | 例which ps | | type -a 命令 | 查看命令所有实现 | -a 显示内建和外部命令 | | coproc 名称 { 命令; }| 创建协程 | 注意空格和分号 | --------------------------------------------------------------------------------