Shell 脚本入门:写好第一个脚本的必备基础

发布时间:2026/10/10 17:34:45

Shell 脚本入门:写好第一个脚本的必备基础 学 Linux 自动化运维Shell 是绕不过去的第一关。这篇把「Shell 是什么、脚本怎么跑起来、变量怎么写」一次讲清读完你能独立写出并执行第一个脚本。文中的变量基础部分与旧文《Shell 变量与环境变量》互补重复的演示已压缩并注明去处。本文概要项目内容文章主题Shell 编程入门概念、脚本执行方式、开发规范与变量基础所属类别Linux 系统管理 · Shell 编程知识关键字bash、幻数、脚本执行方式、环境变量、普通变量、命令替换主线导读先弄清 Shell 与脚本的关系一、二章再把「脚本怎么跑起来」的 5 种方式逐个走一遍三章接着固定一套开发规范四章最后落到变量——变量怎么定义、环境变量怎么持久化、命令结果怎么赋值五章。一、Shell 与 Shell 脚本1.1 Shell 是命令解释器Shell 是一个命令解释器作用是解释执行用户输入的命令与程序。你敲一条它就执行一条这种从键盘输入立刻得到回应的方式叫交互方式。Shell 位于操作系统的外层直接与用户对话把用户输入解释给内核把内核的输出结果返回屏幕。登录 Linux 之后的所有操作都由 Shell 解释执行。Shell 的英文原意是「壳」。上图里命令解释器就像壳一样包住内核这正是这个名字的来历。各系统默认的 Shell 不同操作系统默认 ShellLinuxBourne Again shellbashSolaris / FreeBSDBourne shellshAIXKom shellksh本篇讲 Linux 环境下的 bash。1.2 什么是 Shell 脚本当命令与程序语句不在命令行下执行而是写进一个程序文件来执行时这个文件就叫Shell 脚本。脚本里可以内置很多命令、语句与循环控制一次执行完毕。这种通过文件执行的方式叫非交互方式类似于 DOS 下的批处理程序*.bat。把命令、变量与流程控制语句有机组合起来就成了一个能干活的功能脚本。1.3 为什么要学 ShellShell 擅长处理纯文本数据而 Linux 里几乎一切都是纯文本配置文件、日志文件NFS、Rsync、Httpd、Nginx、LVS、MySQL 等、绝大多数启动文件。它是 Linux/UNIX 系统管理与自动化运维的必备工具系统底层与基础应用软件的核心大都涉及 Shell。合格的运维工程师需要能熟练编写脚本也能读懂系统与软件自带的脚本这样才能提升效率、减少重复劳动。典型场景批量检查多台服务器的运行状态自动化部署、升级各种服务学好 Shell 的推荐基础熟练 vim 与.vimrc配置、掌握 Linux 常用命令、熟悉正则表达式与三剑客grep、sed、awk、了解常见网络服务的部署与排错。学习路径没有捷径多练习 → 多思考 → 多总结再练再想再总结循环坚持。建议从简单判断、简单循环起步多模仿多动手变量命名先按驼峰语法zhbAge规范起来。1.4 脚本语言的种类Shell 是弱类型语言无需先声明变量类型即可使用。Unix/Linux 下主要有两大类家族成员特点Bourne shellsh、ksh、bashLinux 主流bash 兼容 shC shellcsh、tcsh流程控制像 C 语言支持作业控制、别名、命令历史csh 由 Berkeley 大学开发随 BSD UNIX 发布tcsh 是它的增强版加了命令补全在 FreeBSD、MacOSX 上取代了 csh。二、脚本的开头、注释与解释器2.1 幻数#!指定解释器规范的 Shell 脚本第一行要指明由哪个程序来解释脚本内容Linux bash 下一般写#!/bin/bash# 或#!/bin/sh开头的#!两个字符称为幻数。执行脚本时内核会根据#!后面的解释器路径决定用哪个程序解释脚本内容。⚠️注意这一行必须位于脚本的第一行。写在其他位置就只是普通注释内核不会再按解释器规则处理。CentOS 与 RHEL 默认 Shell 都是 bash所以开头不加幻数也会交给 bash 解释。但若希望用其他解释器就必须显式指定否则结果可能不是你要的。养成好习惯任何脚本都写上解释器标识。2.2 注释#后面的内容是注释只给开发者和使用者看解释器不执行。注释可以自成一行也可以跟在命令行尾。没有注释的脚本过一段时间连自己都看不懂团队协作更是困难。关键位置都该写注释。注释尽量不用中文避免换机后乱码。2.3 bash 与 sh 的关系早期 bash 与 sh 略有差别但多数脚本可以不改地在 sh 上跑。系统中 sh 通常是 bash 的软链接[zhbzhb-m2 ~]$ls-l/bin/sh lrwxrwxrwx.1root root411月217:33 /bin/sh -bash所以#!/bin/bash与#!/bin/sh大多没区别但更规范的写法是#!/bin/bash。三、把脚本跑起来的 5 种方式脚本是从上到下、从左到右依次执行的。执行时会向内核请求启动一个新进程在进程里跑脚本遇到子脚本脚本嵌套就先执行子脚本回来再继续。执行前 Shell 会先读环境变量ENV指定的环境文件。五种执行方式与区别方式命令写法是否需执行权限是否新建子进程1. 解释器直跑bash script.sh/sh script.sh否是2. 路径执行./script.sh//home/zhb/script.sh是是3. source 加载source script.sh/. script.sh否否4. 重定向 / 管道bash script.sh/cat script.sh | bash否是5. 放进 PATHscript.sh先cp script.sh ~/bin是是逐条看最简演示# 1. 脚本没有 x 权限、或开头没写解释器时用这种方式[zhbzhb-m2 ~]$bashscript.sh Hello World!# 2. 先加执行权限再用绝对或相对路径执行[zhbzhb-m2 ~]$chmodx script.sh./script.sh Hello World!# 3. source或点号在当前父 Shell 进程里执行变量与函数会留在当前环境[zhbzhb-m2 ~]$sourcescript.sh Hello World!# 4. 不写文件名把脚本内容喂给 bash 的标准输入重定向 / 管道两种写法等价[zhbzhb-m2 ~]$bashscript.sh Hello World![zhbzhb-m2 ~]$catscript.sh|bashHello World!# 5. 复制到 PATH 包含的目录之后直接敲脚本名[zhbzhb-m2 ~]$echo$PATH/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/zhb/.local/bin:/home/zhb/bin[zhbzhb-m2 ~]$cpscript.sh ~/binscript.sh⚠️注意第 4 种与前三种的根本区别是不把脚本名当参数而是把整个文件当标准输入喂给 bash——重定向bash script.sh与管道cat script.sh | bash完全等价。所以它不需要x权限首行#!到这一步也只是普通注释。用它的两个坑①$0变成bash而不是脚本名脚本里若用$(dirname $0)找同目录的配置文件就会跑偏②脚本自己不能再读标准输入——read/cat会和脚本正文抢同一个输入流把还没执行的正文当成输入吞掉实测echo A→read x→echo B→echo C只会输出 A 和 C。它传参也不能直接写bash 参数会被当成「执行一个叫参数的脚本」报No such file or directory没有那个文件或目录得写成bash -s -- 参数。⚠️注意第 3 种方式与其他四种最大的区别是不新建进程。所以只有source能把子脚本里的变量、函数传回当前父 Shell其余方式退出后变量就没了。⚠️注意用./script.sh前必须chmod x否则报「权限不够」。生产上常见事故就是写完忘了加执行权限结果手动或定时执行都没跑起来——不确定权限时直接用第 1 种方式更稳。四、脚本开发规范与书写习惯规范不是强制但能让脚本更易读、更好维护也让协作少踩坑。本节是速览版每一条对应的报错现象与排查办法见专题篇《Shell 脚本格式规范与常见格式错误骨架模板 15 个高频踩坑》。4.1 五条开发规范规范做法首行指定解释器固定写#!/bin/bash开头写版本版权信息# Date/# Author/# Description/# Version可在~/.vimrc里配置自动生成尽量不用中文中英混排易乱码非要加就统一字符集export LANGzh_CN.UTF-8以.sh为扩展名例如script-name.sh存放在固定路径下便于查找与统一管理4.2 六条书写习惯习惯做法成对符号一次写完{}、[]、、、 先成对敲出来再退格填内容中括号两端留空格[ ]、[[ ]]边界与内容之间至少一个空格流程控制先搭框架先把if 条件;then … fi、for … do … done写完整再填内容缩进让代码易读条件与循环体统一缩进变量值加引号常规字符串加双引号需原样输出用单引号等号前后不能有空格符号一律用英文单引号、双引号、反引号都必须是英文半角符号# 一次性搭好的 if 框架if条件内容;then内容fi五、变量基础普通变量、环境变量与定义技巧5.1 什么是变量变量名用一个固定的字符串字母、数字、下划线组合不能以数字开头代替更复杂的内容。变量把数据暂存在内存中调用变量名就能取回对应的值。# 定义变量 username值为 zhb[zhbzhb-m2 ~]$usernamezhb[zhbzhb-m2 ~]$echo$usernamezhb赋值格式变量名 值等号两边不能有空格取值时用$变量名。5.2 变量类型bash 默认不区分变量类型整数、字符串、小数都当字符串处理这与 Java/C 这类强类型语言不同。按范围分两类全局变量在创建它的 Shell 及其派生的任意子进程里可用。局部变量只能在创建它的 Shell 函数或脚本内使用。按来源分两类普通变量由开发者在脚本里自定义也叫常规变量。环境变量定义 Shell 的执行环境又分自定义环境变量与 bash 内置环境变量。5.3 环境变量与持久化环境变量一般指用export导出的变量用来定义 Shell 的运行环境。Shell 靠它确定登录用户名、命令搜索路径、终端类型、登录目录等。所有环境变量都是全局变量可用于所有子进程。在命令行里设的环境变量退出就丢。想永久生效要写进配置文件作用范围配置文件推荐用户级~/.bash_profile、~/.bashrc推荐写~/.bashrc全局级/etc/profile、/etc/bashrc、/etc/profile.d/推荐写/etc/bashrc三种设置写法等价exportNAMEzhb# 常用declare-xNAMEzhb# 效果相同NAMEzhb;exportNAME# 先赋值再导出常用内置环境变量PATH命令搜索路径、HOME家目录、USER当前用户、PWD当前路径、PS1命令行提示符、LANG语言、IFS字符串分隔符、EDITOR默认编辑器、HISTFILE/HISTSIZE/HISTTIMEFORMAT历史命令相关。查看与取消变量三条命令分工不同命令显示范围set所有变量含全局与局部env只显示全局变量含环境变量declare所有变量、函数、整数与已导出的变量unset 变量名消除本地变量与环境变量echo $变量名/printf打印某个变量的值5.4 设置登录后的提示信息这是本篇相对旧文《Shell 变量与环境变量》独有的部分用于给登录用户推一条欢迎语或公告。方法一把字符串写进/etc/motd所有人登录都能看到。[zhbzhb-m2 ~]$vim/etc/motd welcome to zhb linux Shell training.# 登录后效果Welcome to zhb linux Shell training. Last login: Sat Dec312:38:232026from10.1.8.1方法二在/etc/profile.d/下加一个脚本登录时执行。这个目录下的脚本无须加执行权限。[zhbzhb-m2 ~]$sudovim/etc/profile.d/zhb.shechoWelcome to zhb linux Shell training.补充登录前的提示符由/etc/issue提供「上一次登录记录」由 ssh 服务提供在/etc/ssh/sshd_config里由PrintLastLog yes控制默认启用。5.5 登录 Shell 加载环境变量的顺序系统运行 Shell 有三种方式用户登录后默认启动的登录 Shell、非登录交互式 Shell、执行脚本的非交互式 Shell。它们读取的环境文件不同。登录 Shell 的加载顺序先加载/etc/profile这是系统默认的主环境变量文件每个用户登录都会读。再执行/etc/profile.d/目录下的脚本例如字符集设置。然后运行$HOME/.bash_profile其中又会找$HOME/.bashrc.bashrc里再找全局的/etc/bashrc。如果 Shell 不是登录时启动的比如手动敲bash则只加载$HOME/.bashrc并去找/etc/bashrc。⚠️注意希望非登录 Shell 也能读到变量就必须写进$HOME/.bashrc或/etc/bashrc而不是写进$HOME/.bash_profile或/etc/profile。⚠️注意写crond定时任务时脚本要用到的环境变量最好在该脚本里重新定义一遍——定时任务是非登录 Shell读不到你profile里设的东西。5.6 普通变量的定义与引用规则普通变量本地变量只在当前 Shell 生存期内有效退出或另起进程就失效。定义有三种写法含义各不相同# 不加引号值里的变量会被解析[zhbzhb-m2 ~]$a192.168.1.2-$a[zhbzhb-m2 ~]$echoa$aa192.168.1.2-192.168.1.2# 单引号所见即所得不解析[zhbzhb-m2 ~]$b192.168.1.2-$a[zhbzhb-m2 ~]$echob$bb192.168.1.2-$a# 双引号变量与命令先解析再输出[zhbzhb-m2 ~]$c192.168.1.2-$a[zhbzhb-m2 ~]$echoc${c}c192.168.1.2-192.168.1.2-192.168.1.2变量名的要求只能由字母、数字、下划线组成且只能以字母或下划线开头例如zhb、zhb_123、zhb_training。引用规则与引号字面含义的更细展开见旧文《Shell 变量与环境变量》第 3 章本篇不再重复。5.7 把命令结果赋值给变量生产脚本里非常常见。两种写法# 反引号不推荐容易和单引号混淆[zhbzhb-m2 ~]$CMD1ls[zhbzhb-m2 ~]$echo$CMD1script.sh# $() 写法推荐[zhbzhb-m2 ~]$CMD2$(pwd)[zhbzhb-m2 ~]$echo$CMD2/home/zhb[zhbzhb-m2 ~]$echoToday is$(date%A).Today is Friday.5.8 变量定义技巧小结变量名见名知意命名风格固定一种ZhbAge、zhb_age、zhbAge、ZHBAGE都行但别在同一脚本里混用。一般赋值用双引号简单连续的字符串可以不加引号要原样输出用单引号。变量内容来自命令结果时用$()或反引号包住命令。使用时变量名前加$变量名后面紧跟其他字符时用{}把变量名括起来例如${c}abc。在unset、export、(())等场景里引用变量不加$这是例外。本篇只覆盖变量入门。位置参数、状态变量、内置命令与变量子串属于进阶内容见同系列《Shell 变量进阶特殊变量与变量子串实战》变量定义、作用域、引号含义的更细版本见《Shell 变量与环境变量》。附命令英文全称速查表命令 / 缩写英文全称 / 原意作用Shellshell壳包裹内核的命令解释器bashBourneAgainShellLinux 默认 ShellshShellBourne shellbash 的软链接来源kshKornShellAIX 默认 Shellcsh/tcshCShell /tcsh语法接近 C 语言的 Shell 家族#!shebang幻数指定脚本解释器envenvironment显示全局变量setset显示所有变量declaredeclare显示变量、函数、类型与导出状态unsetunset消除变量exportexport导出为环境变量sourcesource在当前 Shell 进程内加载脚本motdmessageoftheday登录后显示的公告profileprofile环境变量配置文件rcrun commands启动时自动执行的命令文件 参考资料官方文档 · 中英双语英文原版GNU Bash Reference ManualShell 语法、变量、启动文件加载顺序的权威说明Bash Startup Files官方手册节点登录 Shell 与非登录 Shell 加载哪些文件中文版Bash 脚本教程阮一峰入门到进阶的中文系统教程其余内容在服务器上直接查不依赖网络、不占链接数manbash# 搜 Startup Files 看环境文件加载顺序helpexport# 内置命令的用法helpread总结入门这条链路的顺序是「Shell 解释命令 → 脚本把命令攒起来批量跑 → 第一行用#!指定解释器 → 用 5 种方式之一跑起来 → 变量负责存取数据」。三件事值得记住脚本第一行必须是解释器source不新建进程、能把变量传回当前 Shell环境变量要长期生效就得写进~/.bashrc或/etc/bashrc。觉得有用可以收藏写脚本踩过坑欢迎在评论区聊聊。
延伸阅读

更多相关文章

2026/10/10 17:29:42

LL(1)文法与四元式:IF-ELSE翻译程序的核心实现

简介:针对编译原理课程中IF-ELSE条件语句的翻译程序设计任务,这份资源提供了基于LL(1)分析法并输出四元式的完整工程实现。资源包共17个文件,压缩包仅417KB,包含Visual Studio工程文件(sln、vcproj)、C源代…

2026/10/10 17:29:42

WorkBuddy FDE:AI原生应用90天端到端交付实战路径

1. 项目概述:这不是一个“教你怎么写代码”的教程,而是一份真实跑通的FDE工作流切片WorkBuddy FDE——这个组合词最近在开发者圈子里出现频率高得有点反常。它不像“React Native”或“Docker Compose”那样有明确的官方定义,而是由一群实际在…

2026/10/10 17:29:42

光缆型号解析:从GB/T 13993.1看结构、选型与工程落地

1. 光缆不是“一根线”,而是一套精密的工程系统很多人第一次接触光缆,下意识会把它当成“升级版网线”——粗细差不多,插在机房里,一端进一端出,通了就行。这种理解在实操中会立刻碰壁。我刚入行时参与某高校园区网络改…

2026/10/10 18:45:28

车载智能座舱核心测试模块Checklist实战拆解

做车载智能座舱测试这些年,最大的感受就是:座舱系统已经不是一个简单的“车机”了,而是一个集仪表、中控、HUD、后排娱乐、语音、C-V2X、车家互联等多维交互于一体的车载移动终端。很多测试同学刚接触座舱项目时,第一反应是“这跟…

2026/10/10 18:45:28

把官方财务运营模板接进你自己的数据:从 CSV 到仪表盘全流程

把官方财务运营模板接进你自己的数据:从 CSV 到仪表盘全流程 【免费下载链接】financial-services 可将 Claude 转变为金融服务专家,适用于投资银行、股票研究等领域。提供核心及专项插件,支持端到端工作流,集成多数据源&#xff…

2026/10/10 18:45:28

基于PJ85718DM与STM32F411RE的双路温度监测方案

1. 项目缘起与整体设计思路嵌入式温度监测这个方向,看起来简单,实际上坑特别多。我最早接触这类需求是在一个HVAC控制柜的改造项目里,当时的要求很朴素:本地要能看到回风温度,远程中控室也要能读到同一路数据&#xff…

2026/10/10 18:40:28

Realtek声卡爆音根治指南:驱动、BIOS与Windows音频深度调优

1. 这不是“爆音”,是Realtek声卡在向你求救最近刷到好几条视频,标题都带着“Realtek声卡一开游戏就炸耳”“看个视频突然滋啦滋啦像烧电线”“耳机里传出电流声,音量调小也没用”——点进去一看,清一色是Windows台式机或笔记本用…

2026/10/10 7:31:36

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/9 20:15:56

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 0:04:53

从逻辑门到计算机:数字电路核心原理与全加器搭建实战

如果你拆过一台旧电脑的主板,盯着那些黑乎乎的小芯片看上一会儿,可能会冒出同一个疑问:这堆引脚密集的元件,到底是怎么“变”出那么复杂的应用的?答案并不在某个神秘的部件里,而是在所有芯片内部都在反复使…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑