当前位置: 首页 > news >正文

七、Linux Shell 与脚本基础

作者:IvanCodes
日期:2025年8月7日
专栏:Linux教程

思维导图 (占位)

****

在掌握了Linux的各种命令之后,我们迈入了一个全新的领域自动化。本章将深入探讨Shell的核心概念区分交互式Shell与Shell脚本,并详细讲解如何创建、配置和执行你的第一个脚本。这是从手动操作自动化运维关键一步

7.1 Shell 简介

1. Shell 的定义与作用

Shell,通常被称为命令行解释器 (Command Line Interpreter),是用户Linux/Unix 操作系统内核进行交互“桥梁”。它扮演着翻译官的角色:

  • 接收用户输入的命令 (如 ls, cd, mkdir)。
  • 解释这些命令的含义。
  • 调用操作系统内核执行相应的功能。
  • 将内核执行的结果返回并显示给用户。

简单来说,没有 Shell,我们就很难方便地直接与强大的操作系统内核打交道了。

2. 常见的 Shell 类型

存在多种不同的 Shell 实现,它们在语法、功能和效率上可能有所差异:

  • bash (Bourne Again SHell): 这是目前最流行、最常用的 Shell,是绝大多数 Linux 发行版的默认 Shell。它兼容 sh,并增加了许多新特性(命令历史、命令补全、作业控制等)。我们后续的脚本主要会以 bash 为基础。
  • sh (Bourne Shell): 一个早期且经典的 Unix Shell。许多旧的或要求高兼容性的脚本仍会使用它。在很多系统中,/bin/sh 可能是一个指向 bash 的符号链接,但 bash 在以 sh 模式运行时会限制某些功能以保持兼容。
  • zsh (Z Shell): 一个功能极其强大的 Shell,提供了比 bash 更丰富的功能、更强的自动补全、主题和插件系统(如 Oh My Zsh),深受许多开发者喜爱。
  • ksh (Korn Shell): 试图融合 sh 的脚本能力和 C Shell 的交互特性。
  • csh/tcsh (C Shell / TENEX C Shell): 语法风格类似 C 语言,交互性较好。

提示: 你可以在终端输入 echo $SHELL 来查看你当前正在使用的 Shell 类型。

3. Shell 与 Shell 脚本的区别

这是一个基础重要的概念:

  • Shell (交互式): 指的是你直接在终端(命令行界面)中输入命令,按回车后立即看到执行结果的环境。这是一种你问我答式的交互方式。
# 这就是在交互式 Shell 中输入命令
ls -l
pwd
  • Shell 脚本 (非交互式): 是一个文本文件,里面包含了一系列按照特定顺序编写的 Shell 命令。你可以一次性执行这个脚本文件,让计算机自动完成一系列复杂的或重复性的任务,实现自动化。这是一种批量处理的执行方式。
# my_script.sh 文件内容可能像这样:
# #!/bin/bash
# echo "开始执行任务..."
# mkdir temp_dir
# cd temp_dir
# echo "任务完成!"

7.2 编写第一个 Shell 脚本

1. 脚本文件的创建与命名

创建一个 Shell 脚本非常简单

  1. 使用文本编辑器 打开你喜欢的文本编辑器(如 vim, nano 等)。
  2. 编写命令: 在文件中输入你的 Shell 命令。
  3. 保存文件 将文件保存。
    • 命名约定: 虽然不是强制性的,但强烈建议将 Shell 脚本文件以 .sh 后缀结尾(例如 my_first_script.sh, backup_data.sh)。这有助于识别文件类型,并且让其他用户(以及未来的你)更容易理解。
2. 指定解释器 (Shebang)

这是 Shell 脚本中至关重要的一行!

  • 什么是 Shebang? 脚本文件的第一行内容,格式为 #!解释器路径
  • 作用: 它告诉操作系统内核,当直接执行这个脚本文件时(即使用 ./script.sh 方式),应该调用哪个解释器来处理文件中的命令。
  • 绝对要求: Shebang 行必须是脚本文件的绝对第一行,前面不能有任何字符,包括空格或空行。

常见的 Shebang 选项详解:

  1. #!/bin/bash:

    • 指定使用 Bourne Again Shell (bash) 来执行脚本。
    • 优点: 可以使用 bash 提供的所有扩展功能(如数组、双方括号 [[ ]] 条件测试等)。
    • 缺点: 如果系统没有安装 bash 或者 bash 不在 /bin/bash 路径下,脚本会执行失败。可移植性稍差
  2. #!/bin/sh:

    • 指定使用 Bourne Shell (sh) 来执行脚本。
    • 优点: 目标是编写符合 POSIX 标准的脚本,具有更好的可移植性。在很多系统中,/bin/sh 是一个指向 bashdash 等兼容 Shell 的符号链接。
    • 缺点: 不能使用 bash 等现代 Shell 的扩展语法和功能
  3. #!/usr/bin/env <interpreter> (例如 #!/usr/bin/env bash):

    • 这是强烈推荐的一种方式,特别是对于需要分发的脚本。
    • env 是一个命令,它会在系统的PATH 环境变量所指定的目录中查找第一个找到的 <interpreter>(如 bash, python 等)并使用它。
    • 优点: 极大地提高了可移植性。不同系统或用户可能将解释器安装在不同的路径下(如 /usr/bin/bash, /usr/local/bin/bash)。使用 env 可以确保只要解释器在用户的 PATH 中,脚本就能找到它
    • 缺点:极其微小的额外启动开销。

如何选择 Shebang?

  • 为了最大化可移植性,通常首选推荐使用 #!/usr/bin/env <interpreter> 的形式。
  • 如果脚本严格依赖 bash 的特性,并且只在已知环境下运行,#!/bin/bash 也可以接受。
3. 脚本的执行方式

你有三种主要的方式来运行你的 Shell 脚本:

  1. 作为解释器的参数执行:
    • 这种方式不需要给脚本文件设置执行权限
    • 直接调用 Shell 解释器 (如 bash),并将脚本文件名作为参数传递给它。
    • 核心特点: 脚本在子 Shell (subshell) 中执行,脚本中对环境的修改(如 cd)在脚本结束后不会影响当前的 Shell 环境。
    • 命令格式:
bash my_script.sh
  1. 赋予执行权限后直接运行:
    • 第一步:添加执行权限 (x)
chmod +x my_script.sh
*   第二步:<font color="saddlebrown">**直接执行**</font>。如果脚本在<font color="darkmagenta">当前目录</font>,你需要使用 `./` 来执行。
./my_script.sh
*   **核心特点:** 这是最<font color="firebrick">**标准、常用**</font>的执行方式。Shebang 行 `#!` <font color="darkslategray">决定了</font>使用哪个解释器。脚本同样在<font color="indigo">**子 Shell**</font> 中执行,对当前 Shell 环境<font color="blue">**没有持久影响**</font>。
*   **为什么需要 `./`?** 出于<font color="red">**安全考虑**</font>。Linux 系统默认<font color="green">**不会**</font>在当前目录下查找可执行文件。使用 `./` 可以<font color="orange">明确指定</font>执行当前目录下的文件,防止<font color="purple">意外执行</font>了与系统命令同名的<font color="teal">恶意脚本</font>。
  1. 使用 source. 命令在当前 Shell 环境中执行:
    • source 是一个 Shell 内建命令,它的简写形式是一个点 (.)。
    • 这种方式也不需要执行权限 (只需要读权限 r 即可)。
    • 命令格式:
source my_script.sh
# 或者使用点号 (点号和脚本名之间必须有空格!)
. my_script.sh
*   **<font color="navy">核心区别:</font>** 使用 `source` 或 `.` 执行时,脚本中的命令<font color="olive">**直接在当前的 Shell 环境中**</font>执行,<font color="darkcyan">**而不是**</font>启动一个新的<font color="saddlebrown">子 Shell</font>。
*   **主要用途:** 脚本中定义的<font color="darkmagenta">**变量、函数、别名 (alias)**</font>,或者执行的 `cd`、`export` 等命令,在脚本执行完毕后会<font color="firebrick">**保留在当前的 Shell 会话中**</font>。因此,它常用于:*   <font color="darkslategray">加载配置文件</font> (如 `.bashrc`, `.profile`)。*   <font color="indigo">设置环境变量</font>供后续命令使用。*   <font color="blue">定义可以在</font>当前终端后续使用的<font color="red">函数库</font>。

执行方式对比小结:

执行方式需要执行权限 (x)?在子 Shell 中执行?对当前 Shell 环境的影响主要用途
bash script.sh运行一次性任务,不需改变当前环境
./script.sh标准的脚本执行,分发工具脚本
source script.sh (需r)有 (持久)加载配置/环境/函数,改变当前环境

7.3 注释与可读性

编写清晰易懂的脚本至关重要,而注释是实现这一目标的关键工具

1. 单行注释
  • 在 Shell 脚本中,使用 # 符号来表示单行注释。
  • # 开始,直到该行的末尾,所有的内容都会被 Shell 解释器忽略,不会被执行。
# 这是一个完整的单行注释,用于说明脚本的目的
echo "Hello, World!" # 这也是一个注释,解释这行命令的作用
2. 多行注释的实现方式

Shell 本身没有提供原生多行注释块语法。但是,可以通过技巧来实现类似的效果:

  • 方法一:使用 Here Document (推荐)
    将你想要注释掉的内容通过 Here Document (<<LIMITER ... LIMITER) 重定向给一个空命令 : (冒号)。
: <<'COMMENT_BLOCK'
这里是第一行注释内容。
这里是第二行注释内容。
这整块代码/文字都不会被执行。
COMMENT_BLOCK
  • 方法二:连续使用单行注释
    这是最简单直接的方法,只需在每一行注释前都加上 #
3. 良好的注释习惯
  • 解释“为什么”(Why),而不是“干什么”(What): 好的代码本身应能说明它在做什么。注释应该聚焦于解释为什么选择这种实现方式、背后的逻辑或潜在的陷阱
  • 保持注释简洁同步: 当代码发生变化时,务必更新相关的注释。
  • 文件头注释: 在脚本文件的开头添加注释块,说明脚本的用途、作者、创建日期、版本号、使用方法等信息,是一个非常好的实践
#!/usr/bin/env bash
# ==============================================================================
# Script Name:    backup_database.sh
# Description:    Performs a daily backup of the production PostgreSQL database.
# Author:         Your Name <your.email@example.com>
# Date Created:   2023-05-02
# Version:        1.2
# Usage:          ./backup_database.sh
# ==============================================================================

总结

本章我们奠定了Shell脚本编程的坚实基础。我们理解了Shell作为命令行解释器的角色,区分了交互式Shell和Shell脚本的不同用途。最重要的是,我们详细学习了如何创建一个脚本,正确使用Shebang来指定解释器,并掌握了三种核心的执行方式及其对当前环境不同影响。良好的注释习惯贯穿我们后续的自动化编程之旅。


练习题 (共15道)

题目:

  1. 简述 Shell 在 Linux/Unix 系统中的主要作用是什么?
  2. Shell 脚本的第一行 #!/bin/bash 有什么作用?它通常被称为什么?
  3. 如何让一个名为 my_script.sh 的 Shell 脚本文件,能够直接通过 ./my_script.sh 的方式运行?请写出关键命令。
  4. 执行 Shell 脚本时,使用 bash script.shsource script.sh 的主要区别是什么?哪种方式会影响当前的 Shell 环境?
  5. 在 Shell 脚本中,如何添加单行注释?请给出表示注释的符号。
  6. Shell 没有原生的多行注释块语法。请描述一种常用的、基于 Here Document 的方法来模拟多行注释。
  7. 为什么通常推荐使用 #!/usr/bin/env bash 而不是直接使用 #!/bin/bash 作为 Shebang?
  8. 如果一个脚本文件 test.sh 没有执行权限,但有读权限,以下哪种方式可以成功执行它? A) ./test.sh B) bash test.sh C) source test.sh D) B和C均可
  9. 要查看当前系统默认的 Shell 是什么,应该执行什么命令?
  10. . (点号) 命令和 source 命令在执行脚本时有什么关系?
  11. 为什么在执行当前目录下的脚本时,通常需要在脚本名前加上 ./
  12. 你为一个脚本添加了 chmod +x script.sh 权限,但执行 ./script.sh 时提示 “bad interpreter: No such file or directory”。最可能的原因是什么?
  13. 写一个标准的文件头注释块,包含脚本名称、描述和作者。
  14. zshbash 都是 Shell 的一种实现,这种说法正确吗?
  15. 如果你有一个脚本 setup_env.sh,其内容是 export MY_VAR="hello"。为了在当前终端会话中设置 MY_VAR 这个环境变量,你应该使用哪种方式执行这个脚本?

答案与解析:

  1. Shell 的作用:

    • 解析: Shell 是命令行解释器,作为用户操作系统内核交互的接口或桥梁。它负责接收和解释用户的命令,调用内核执行,并返回结果
  2. Shebang 的作用:

    • 解析: #!/bin/bash 的作用是指定解释器。当脚本被直接执行时,操作系统会根据这一行找到 /bin/bash 解释器来处理脚本内容。这一行通常被称为 Shebang
  3. 添加执行权限:

chmod +x my_script.sh
*   **解析:** `chmod +x` 命令为文件<font color="firebrick">添加执行权限</font>,这是<font color="darkslategray">能够直接</font>通过 `./` 方式运行脚本的<font color="indigo">先决条件</font>。
  1. bash vs source 的区别:

    • 解析: 主要区别在于执行环境bash script.sh 会启动一个新的子 Shell 来执行脚本,不影响当前环境。source script.sh 则在当前的 Shell 环境中执行,会影响当前环境(如设置变量、定义函数)。
  2. 单行注释符号:

    • 解析: 在 Shell 脚本中,使用 # 符号来添加单行注释。
  3. 模拟多行注释:

    • 解析: 使用 Here Document 并将其重定向给一个空命令 :。例如:: <<'COMMENT' ... COMMENT
  4. env 的优势:

    • 解析: #!/usr/bin/env bash 提高了脚本的可移植性。它会在用户的PATH环境变量中查找bash,而不是硬编码/bin/bash。这使得脚本在不同系统自定义环境更容易成功运行。
  5. 无执行权限的执行方式:

    • 答案: D) B和C均可
    • 解析: bash test.shsource test.sh 都是直接调用解释器或内建命令来读取和执行脚本内容,因此只需要对文件有读权限即可,不需要执行权限。
  6. 查看默认 Shell:

echo $SHELL
*   **解析:** `$SHELL` 是一个<font color="purple">环境变量</font>,它<font color="teal">存储了</font>当前用户<font color="brown">登录时</font>使用的<font color="darkgreen">默认 Shell</font> 的路径。
  1. .source 的关系:

    • 解析: 它们是等价的. (点号) 是 source 命令的简写形式,两者都用于在当前 Shell 环境中执行脚本。
  2. 使用 ./ 的原因:

    • 解析: 出于安全原因。Linux 系统默认不会在当前工作目录下搜索命令./ 明确地告诉 Shell “请在当前目录下查找并执行这个文件”,防止意外运行了与系统命令同名恶意脚本
  3. “bad interpreter” 错误原因:

    • 解析: 这个错误最常见的原因是脚本的Shebang行 (#!...) 指定了一个不存在路径错误的解释器。另一个可能的原因是脚本文件从Windows系统拷贝过来,包含了回车符 (\r),导致解释器路径 (如 /bin/bash\r) 无效。
  4. 标准文件头注释:

#!/usr/bin/env bash
# ===================================================
# Script Name:   my_awesome_script.sh
# Description:   This script does awesome things.
# Author:        IvanCodes
# ===================================================
*   **解析:** 一个<font color="navy">好的文件头</font>注释能让<font color="olive">任何人</font>快速<font color="darkcyan">理解脚本</font>的基本信息,是<font color="saddlebrown">专业脚本编写</font>的<font color="darkmagenta">标志</font>。
  1. zshbash 的关系:

    • 答案: 正确。
    • 解析: 两者都是不同的 Shell 实现,都扮演着命令行解释器的角色,只是在功能、语法细节和用户体验上有所不同
  2. 设置环境变量的执行方式:

    • 答案: source setup_env.sh. setup_env.sh
    • 解析: export 命令只有在当前 Shell 环境中执行时才能真正设置对当前会话生效的环境变量。如果使用 bash setup_env.shexport 会在子 Shell 中执行,脚本一结束,子 Shell 销毁,设置的环境变量也就随之消失了。
http://www.xdnf.cn/news/1255177.html

相关文章:

  • C语言memmove函数详解:安全高效的内存复制利器
  • 使用Spring Boot + Angular构建安全的登录注册系统
  • 自动化办公革命:3小时完成8小时工作量
  • 每日算法刷题Day58:8.7:leetcode 单调栈5道题,用时2h
  • Python 基础详解:数据类型(Data Types)—— 程序的“数据基石”
  • 超高车辆如何影响城市立交隧道安全?预警系统如何应对?
  • 鸿蒙网络编程系列61-仓颉版基于TCP实现最简单的HTTP服务器
  • 计算机网络:固定网络位长度子网划分flsm和可变长子网掩码划分vlsm的区别
  • 【C++】哈希表原理与实现详解
  • 代码随想录day58图论8
  • Mysql数据仓库备份脚本
  • Android视图状态以及重绘
  • 快速开发实践
  • 内网穿透原理和部署教程
  • 【Kubernetes】部署 kube-bench 实现 K8s 最佳实践
  • tcpdump问题记录
  • Linux下动态库链接的详细过程
  • 【数据结构初阶】--排序(五)--计数排序,排序算法复杂度对比和稳定性分析
  • Python Socket 脚本深度解析与开发指南
  • MySQL梳理四:事务日志机制和多版本并发控制(MVCC)
  • SpringMvc的原理深度剖析及源码解读
  • 前端页面直接生成PDF下载文件
  • “物联网+职业本科”:VR虚拟仿真实训室的发展前景
  • 物联网架构全解析:华为“1+2+1”与格行随身WiFi,技术如何定义未来生活?
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的微商产品经营策略研究
  • 技术优势铸就行业标杆:物联网边缘计算网关凭何引领智能变革?
  • 008 前端vue
  • Spring AOP动态代理核心原理深度解析 - 图解+实战揭秘Java代理设计模式
  • RabbitMQ-日常运维命令
  • 嵌入式硬件中MOSFET基本原理与实现