当前位置:首页 > 工具 > 正文内容

Shell编程基础入门指南

访客 工具 2026年6月25日 1

计算机只能识别二进制机器语言(如11000000这样的序列),无法直接理解人类编写的源代码。为了让程序能够在计算机上运行,需要借助编译器或解释器将源代码转换为机器可执行的指令。

编程语言的两种执行方式

编译型语言

这类语言在执行前需要经过专门的编译过程,将源代码转换为目标机器码。编译完成后,运行时直接执行编译后的结果,无需再次翻译。因此执行效率较高,但依赖于特定的编译器,跨平台能力相对较弱。典型代表包括C、C++等语言。

解释型语言

解释型语言不需要预先编译,程序运行时由解释器逐行翻译成机器语言,每执行一次都需要翻译一次。由于翻译过程贯穿整个运行阶段,因此执行效率相对较低。Python、JavaScript、Ruby以及Shell脚本都属于解释型语言。

执行方式对比总结

编译型语言执行速度更快,但跨平台能力较弱;解释型语言虽然执行效率稍低,但具有良好的跨平台兼容性。通常情况下,底层开发、系统程序和大型应用会选择编译型语言;而服务器脚本、跨平台工具等场景则更适合使用解释型语言。

Shell的概念解析

Shell是Linux系统中位于内核之上的命令解释层,它充当用户与操作系统内核之间的桥梁。Shell接收用户输入的命令,将其转换为内核能够理解的形式传递给内核执行,同时将执行结果呈现给用户。这种交互方式既可以是交互式的(从键盘直接输入命令并立即获得响应),也可以是非交互式的(通过脚本文件批量执行命令)。

从功能角度来看,Shell命令行解释器的主要作用是实现用户与内核的沟通。用户输入指令后,Shell将其转换为内核可识别的二进制格式,内核分析指令后向CPU发出进程调度和资源分配指令,最终由硬件设备展示执行结果。

Shell脚本的定义与用途

Linux环境下的Shell脚本是一个具有执行权限的文本文件,通过它可以自动化完成特定功能任务。简单来说,Shell脚本就是将需要执行的命令保存到文本文件中,然后按照预定顺序依次执行。由于Shell是解释型语言,因此无需进行编译过程。

Shell脚本的本质可以概括为:命令集合 + 脚本规范格式 + 特定语法结构 + 编程思想 = Shell脚本

Shell脚本的典型应用场景

日常运维中,Shell脚本常用于以下方面:

  • 自动化软件部署(如LAMP、LNMP、Tomcat等环境的一键搭建)
  • 系统初始化和批量管理(批量修改主机密码、推送公钥等)
  • 日志分析处理(统计网站访问量、生成报表)
  • 数据备份(数据库定期备份、日志转储)
  • 系统监控(资源使用情况监控、告警触发)

Shell脚本学习路径

  1. 熟悉常用命令的功能和使用场景
  2. 掌握脚本的标准格式规范(魔术字节声明、正确的执行方式)
  3. 精通脚本基本语法(变量、条件判断、循环等核心知识)

学习的核心秘诀在于:先看懂模仿练习,最后独立思考编写。

脚本示例演示

示例一:基础日志清理脚本

cd /var/log
cat /dev/null > messages
echo "日志清理完成"

这个脚本存在的问题是没有权限检查和流程控制逻辑,不够完善。

示例二:带错误处理的日志清理脚本

#!/bin/bash
# 日志清理脚本增强版
LOG_DIR=/var/log
ADMIN_UID=0

# 检查是否以管理员权限运行
if [ "$UID" -ne "$ADMIN_UID" ]; then
    echo "需要管理员权限才能执行此脚本"
    exit 1
fi

cd $LOG_DIR || {
    echo "无法切换到目标目录" >&2
    exit 1
}

cat /dev/null > messages && echo "日志清理完成"
exit 0

该版本增加了用户身份验证、目录切换错误处理等机制,使脚本更加健壮。

清空日志文件的几种方式:

echo > test.log
> test.log
cat /dev/null > test.log

脚本执行原理

执行Shell脚本时会启动子Shell进程。从命令行启动的脚本会继承当前Shell的环境变量;而系统自动执行的脚本(非交互式启动)则需要自行定义所需的环境变量。

进程与Shell的关系

每个进程只能感知到内核和自身,无法直接了解其他进程的存在。进程是程序的一次执行实例,不同的进程即使名称相同,进程号也必然不同。多个用户可以同时登录系统,每个用户的Shell会话相互独立;同一用户也可以从不同终端登录,每个会话对应不同的Shell进程。父Shell中设置的变量不会自动传递给子Shell,反之亦然。

Shell与其他脚本语言的区别

Shell的优势在于处理操作系统底层任务,这得益于其丰富的命令生态(如grep、sed、awk等工具的配合)。对于一键安装、监控告警、日常运维任务等场景,Shell脚本开发更为高效简洁。

PHP、Python则更适合开发运维管理工具和Web界面应用。

Shell脚本特别擅长处理纯文本类型的数据,而Linux系统中几乎所有配置文件和日志文件(如Nginx、Apache、Rsync等服务的配置和日志)都是纯文本格式。掌握Shell脚本能够充分发挥Linux系统的潜力。

Linux系统支持的Shell类型

/bin/sh        - Bourne Shell的符号链接
/bin/bash      - Linux默认Shell,功能最为完善
/sbin/nologin  - 非交互式Shell,禁止登录
/bin/dash      - 轻量级Shell,执行效率高但功能较少
/bin/tcsh      - csh的增强版本,完全兼容csh
/bin/csh       - C语言风格的Shell

Shell脚本语言属于弱类型语言,常用的标准Shell包括Bourne Shell(sh)和C Shell(csh),其中Bourne Shell已被bash取代。

查看当前系统默认Shell:

echo $SHELL
# 输出:/bin/bash

grep root /etc/passwd
# 输出:root:x:0:0:root:/root:/bin/bash

Bash Shell的基本特性

Bash提供了丰富的功能特性,包括命令补全、快捷键操作、命令历史、别名定义、标准输入输出重定向和管道操作等。

命令补全功能

  • 命令补全:在PATH环境变量指定的路径中搜索以输入字符串开头的可执行文件。如果找到多个匹配项,按两次Tab键显示完整列表;否则直接补全。
  • 路径补全:根据给定的路径前缀自动补全文件名。

常用快捷键

快捷键 功能说明
Ctrl+a 跳至命令行首
Ctrl+e 跳至命令行尾
Ctrl+u 删除光标至行首的内容
Ctrl+k 删除光标至行尾的内容
Ctrl+l 清屏
Ctrl+c 终止前台进程
Ctrl+z 暂停前台进程并放入后台
Ctrl+d 退出Shell
Ctrl+r 搜索历史命令

通配符使用

  • * - 匹配任意数量的字符
  • ? - 匹配单个任意字符
  • [list] - 匹配指定列表中的任意单个字符
  • [!list] - 匹配除指定列表外的任意单个字符
  • {str1,str2,...} - 匹配多个指定字符串之一

示例演示:

touch file{1..3}           # 创建file1, file2, file3
touch file{1..13}.jpg      # 创建file1.jpg到file13.jpg
ls file*                   # 列出所有file开头的文件
ls *.jpg                   # 列出所有jpg文件
ls file?                   # 列出file后跟单个字符的文件
ls file[0-9].jpg           # 列出file0.jpg到file9.jpg

引号的区别与用法

  • 双引号(""):保留引号内内容的整体性,但允许通过$符号引用变量
  • 单引号(''):将内容作为整体看待,禁止变量引用,特殊字符均视为普通字符
  • 反引号(``):与$()功能相同,用于执行命令并获取输出,嵌套使用时反引号可能出现问题

示例对比:

echo "$(hostname)"
# 输出:server

echo '$(hostname)'
# 输出:$(hostname)

echo $(date +%F)
# 输出:2024-01-15

echo `echo $(date +%F)`
# 输出:2024-01-15

命令历史机制

系统默认保存最近执行的1000条命令历史,记录位置为~/.bash_history。

相关环境变量:

  • PATH:命令搜索路径
  • HISTSIZE:历史记录缓冲区大小

history命令常用选项:

  • -c:清空命令历史
  • -d OFFSET [n]:删除指定位置的命令
  • -w:保存历史记录到文件

历史命令调用技巧:

  • !n:执行第n条历史命令
  • !-n:执行倒数第n条历史命令
  • !!:执行上一条命令
  • !string:执行最近以指定字符串开头的命令
  • !$:引用上一条命令的最后一个参数

命令别名机制

定义语法:

alias CMDALIAS='COMMAND [options] [arguments]'

特性说明:在Shell中定义的别名仅在当前Shell会话中有效,别名作用范围仅限于当前进程。

相关操作:

alias              # 查看已定义的别名
unalias 别名       # 删除指定别名
unalias -a         # 清除所有别名
alias 新别名='实际命令'  # 定义新别名

别名持久化配置:

vim ~/.bashrc      # 仅对当前用户生效
vim /etc/bashrc    # 对所有用户生效

标准输入输出与重定向

三大标准流

类型 设备文件 文件描述符 默认设备
标准输入 /dev/stdin 0 键盘
标准输出 /dev/stdout 1 显示器
标准错误 /dev/stderr 2 显示器

重定向操作

防止意外覆盖:

set -C    # 禁止对已存在文件使用覆盖重定向
>|       # 强制覆盖输出
set +C    # 关闭上述保护功能

重定向类型说明:

类型 操作符 用途
输入重定向 < 将输入来源从键盘改为指定文件
输出重定向 > 将正常输出保存到文件(覆盖)
输出重定向 >> 将正常输出追加到文件
错误重定向 2> 将错误信息保存到文件(覆盖)
错误重定向 2>> 将错误信息追加到文件
混合重定向 &> 同时重定向正确和错误输出到同一文件
混合重定向 &>> 追加方式重定向正确和错误输出

管道操作

管道将前一个命令的输出作为后一个命令的输入:

命令1 | 命令2 [| 命令n]

典型应用示例:

pgrep -l "." | wc -l       # 统计运行中的进程总数
ifconfig | grep "HWaddr"   # 获取本机MAC地址

命令组合逻辑

命令1 ; 命令2     # 顺序执行,无逻辑关联
命令1 && 命令2    # 仅当命令1成功时执行命令2
命令1 || 命令2    # 仅当命令1失败时执行命令2

Shell脚本的创建与执行

Shell脚本由Linux命令、Bash内置命令、流程控制语句和注释组成。

脚本开头的解释器声明

规范脚本第一行需指定解释器路径:

#!/bin/bash
# 或
#!/bin/sh

#!称为魔术数字(shebang),内核根据它来确定使用哪个程序解释执行脚本内容。此行必须位于脚本最前端,否则会被视为普通注释。

为提高兼容性,也可使用env命令:

#!/bin/env bash

不同脚本语言的标准开头:

#!/bin/sh
#!/bin/bash
#!/usr/bin/awk
#!/bin/sed
#!/usr/bin/perl
#!/usr/bin/env python

CentOS和RedHat系统默认Shell为bash。建议即使使用默认bash,也养成添加shebang的习惯。若未指定解释器,则需手动使用对应解释器执行:

bash test.sh
python test.py

脚本注释规范

#符号后的内容为注释,注释不会被执行,仅供阅读理解。良好的注释习惯有助于团队协作和个人后续维护。

常用注释格式:

# 脚本名称
# 功能描述
# 存放路径
# 使用方法
# 更新记录

三种脚本执行方式

方式一:使用解释器直接运行

bash script-name.sh
# 或
sh script-name.sh

适用于脚本文件无执行权限或未指定解释器的情况。

方式二:直接执行脚本文件

/path/script-name.sh
# 或
./script-name.sh

需要先添加执行权限:

chmod u+x script-name.sh
chmod 755 script-name.sh

方式三:source或点号加载执行

source script-name.sh
# 或
. script-name.sh

此方式不需要执行权限,且脚本中的变量和函数会在当前Shell中生效,而非创建子Shell执行。

三种执行方式的差异演示

创建测试脚本:

cat > test.sh
echo '当前目录:' `pwd`

使用方式一执行:

sh test.sh
echo $userdir
# 输出:空(变量未传递到当前Shell)

使用方式三执行:

source test.sh
echo $userdir
# 输出:/home/user(变量成功传递到当前Shell)

结论:source和点号方式执行脚本时,脚本中定义的变量和函数会在当前Shell中保持有效;而bash/sh方式执行则会启动子Shell,脚本结束后变量无法保留。

系统服务脚本中常见这种用法:

. /etc/rc.d/init.d/functions

Shell脚本开发规范

  1. 指定解释器:脚本开头必须声明shebang
  2. 添加版权信息:包含日期、作者、功能说明、版本号等元数据
  3. 使用英文注释:避免中文乱码问题
  4. 统一文件扩展名:建议使用.sh作为脚本文件后缀
  5. 成对书写语法元素:如[]{}''""$()等需一次性成对写出,防止遗漏
  6. 保持适当缩进:通过缩进提高代码可读性
  7. 流程控制语句整体构建:先写完if/for/while等结构框架,再填充具体逻辑

示例规范写法:

if 条件判断
then
    执行内容
fi

for 变量 in 列表
do
    循环体
done

遵循这些规范能够显著减少编程错误,提高脚本质量和工作效率。

标签: Linux

相关文章

Trojan服务器搭建与配置

一、整体架构(先对齐认知)Clash Meta (PC / iOS / Android)        ↓ TLS   Trojan Server (443)        ↓     InternetTrojan 的核心是: TLS + HTTPS 流量伪装 看起来像正常网站 非常适合...

Tailscale 的详细用法

Tailscale 是一种基于 WireGuard 协议 的 零配置 VPN(虚拟私有网络)服务,让设备之间能够 安全、加密地直接连接,就像它们在同一个本地网络一样。它的核心特点是 简单、安全、跨平台。Tailscale 非常适合 没有公网 IP、两台电脑不在同一局域网 的场景。 简单来说,Tailscale 是什么?Tailscale 是一款让你的各种设备(电脑、服务器、手机...

Clash Tun 模式 导致 爱快(iKuai SD-Wan)内网域名无法访问

一、Clash  DNS 配置dns:  enable: true  listen: 0.0.0.0:53  ipv6: true  enhanced-mode: redir-host  nameserver:    - 223.5.5.5    - 223.6.6.6iKuai 内网域名 ...

深入解析Node.js运行环境与异步I/O架构

深入解析Node.js运行环境与异步I/O架构

核心定义与价值Node.js本质上是一个JavaScript运行环境,而非编程语言或应用框架。它赋予了JavaScript脱离浏览器在服务端、命令行工具及网络应用中执行的能力。其核心意义在于:用单一语言打通前后端开发壁垒。基于事件驱动与非阻塞I/O的架构特性,Node.js在处理API网关、实时通信及微服务等I/O密集型场景时表现卓越,已成为现代后端工程的主流选择。浏览器沙箱限制1995年Java...

ADO.NET SQL参数化查询的最佳实践

在 ADO.NET 中执行 SQL 查询时,参数化查询是一种关键的安全措施和性能优化手段。它通过将 SQL 命令和用户提供的数据分开处理,有效防止了 SQL 注入攻击,并有助于数据库缓存执行计划。下面总结了几种常用的参数化查询方式。 1. 使用 SqlParameter 对象(推荐) 这是最推荐的参数化查询方式。通过显式创建 SqlParameter 对象,您可以精确控制参数的类...

基于ELK的日志集中化分析系统搭建

构建统一日志管理平台的必要性 在分布式架构中,各服务节点独立运行,日志分散存储于不同主机。传统通过命令行工具如grep、awk逐个检索日志的方式,在数据量庞大时效率极低,难以实现快速定位问题。为提升运维效率,需建立集中式日志处理体系,具备日志采集、传输、存储、分析与告警能力。 ELK技术栈核心组件解析 Elasticsearch:分布式搜索引擎,支持全文检索、实时数据分析和高可用集群部署,...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。