首页 / 资讯中心 / 文章详情

2026年Shell编程入门:自动化时代的底层基石

2026年Shell编程入门:自动化时代的底层基石 ★ FEATURED ARTICLE
1. 为什么2026年还要啃Shell这门手艺1.1 所有自动化都跑在Shell的肩膀上做了十来年运维和脚本开发近几年越来越多朋友问我同一个问题现在都有了各种自动化平台、可视化运维系统甚至AI都能写代码了还有必要花时间学Linux Shell编程吗我的回答一直很干脆有必要而且越早学越值。2026年了云原生、容器、CI/CD满天飞但只要你把任何一个自动化流程解剖到底最后真正在服务器上干活的依然是那一行行Shell命令和Shell脚本。部署平台点一下按钮底层执行的是Shell容器启动要跑初始化逻辑入口多半是Shell脚本定时备份、日志切割、故障巡检这些活儿在绝大多数公司里到现在还是Shell脚本在扛。Shell不是被淘汰的老技术它恰恰是所有现代自动化体系最底层的那个地基。对想进入运维、后端、嵌入式甚至是数据分析领域的人来说Shell编程是那种看起来不显眼但一遇到实际问题就要靠它救命的能力。它不需要装额外环境几乎每一台Linux服务器都自带学完就能用性价比极高。这篇文章是我基于自己这些年实际踩坑和日常使用整理出来的快速入门路线针对的是2026年还在用Linux、还在和命令行打交道的朋友尤其是零基础想系统入门的初学者。1.2 从敲命令到写脚本转变的是编程思维很多新手会有个困惑我会敲几十条Linux命令了为什么还是写不出脚本这是非常正常的阶段。敲命令本质是一次性的操作就像你拿起刀切了一根黄瓜写脚本则是把整个做菜流程编排成工序你要考虑先放油还是先放菜、火候怎么控制、什么时候出锅。两者差的不是命令数量而是编程思维。Shell脚本的核心思维其实只有三件事把重复的操作参数化、把判断和循环加进去、把错误处理补上。举个很常见的场景你有100个文件要统一重命名如果一个个敲mv命令手疼不说还容易出错写成脚本后一个for循环全部搞定。同一个需求从手工敲命令到拿脚本跑效率提升是数量级的这就是学Shell编程真正的收益所在。1.3 我能用Shell做什么典型应用场景很多初学者不知道该往哪用力我先给你列几个Shell编程的高频实际场景你心里有个数批量操作批量重命名文件、批量修改配置、批量打包日志。系统巡检定时检查CPU、内存、磁盘占用率超阈值就告警。数据备份把数据库导出、压缩、按日期命名、上传到远端存储。日志处理从几十GB的日志里grep出关键错误再统计出现次数。一键部署把拉代码、装依赖、重启服务、健康检查这些步骤串成一个脚本。自动化测试在CI流程里做接口冒烟测试、环境准备、结果清理。这些需求几乎每个用Linux的团队都会碰到。你不需要等自己学完了再动手完全可以一边学一边写遇到什么需求就写什么脚本这才是最快的进步方式。2. Shell脚本的语法骨架变量、参数与控制流2.1 变量与作用域别小看export那点事Shell编程的入门第一课永远是变量。它的语法看起来简单但坑也不少。定义变量和取值的标准写法如下# 定义变量等号两边绝对不能有空格 namezhangsan version2026 echo Hello, $name, version is ${version}这里必须强调一个新手最容易犯的错等号两边不能留空格。name zhangsan这种写法在别的语言里是赋值到了Shell里就会被拆成三个词系统会试图把name当成命令去执行直接报错或者产生诡异行为。我当年就因为这个卡了很久。关于引号规则是双引号里的变量会展开比如Hello, $name输出的是Hello, zhangsan。单引号里的内容原样输出Hello, $name会原封不动打出Hello, $name。不加引号时遇到空格或特殊字符容易被拆词所以字符串尽量加双引号是稳妥习惯。再说说export。很多初学者一开始不理解为什么我在脚本里定义了一个变量脚本跑完了再看终端里还是空的。# test.sh export MY_VARhello # 在终端执行 ./test.sh echo $MY_VAR # 输出空原因是每执行一个脚本系统都会启动一个子Shell进程脚本里定义的变量只在子进程里有效脚本一结束进程销毁变量也就没了。export的作用不是让变量跑到父进程去而是把变量标记为环境变量这样它可以在当前进程的所有子进程里被继承。这个知识点特别重要。比如你要在脚本里调用另一个脚本希望对方也能读到你的变量就必须export。但如果只是脚本内部临时计算用的变量不导出也没有问题。用生活类比来说export相当于你给高铁票办了个行李直挂儿孙后代子进程都能拿到不export就像是手提行李自己拎着走孩子上车前你还得亲手递给他。2.2 参数处理shift与位置参数的灵活应用写脚本和敲命令最大的不同之一就是脚本要接收参数。Shell里用位置参数来处理$0脚本名本身$1、$2、$3第1、2、3个参数$#参数总个数$所有参数列表每个参数独立$*所有参数当成一个整体字符串举个实际例子。假设我要写一个脚本它可以接收任意多个文件名逐个显示类型信息#!/bin/bash echo 脚本名: $0 echo 参数个数: $# for file in $ do echo 检查文件: $file file $file done这里有个关键点遍历参数时务必写$不要裸写$或$*。加双引号能确保参数里哪怕含有空格、特殊字符也能被当成一个整体不会意外拆分。如果你还没理解可以想想一个文件名叫my documents.txt不加引号它就会裂成两个词处理逻辑直接就崩了。再讲shift。这个命令是让你把参数往左挪一位原来$2变成$1$3变成$2同时$#减1。它特别适合用while循环一个一个消费参数尤其是处理选项值的场景。#!/bin/bash while [ $# -gt 0 ] do case $1 in -f|--file) shift file$1 ;; -d|--dir) shift dir$1 ;; *) echo 未知参数: $1 exit 1 ;; esac shift done echo 文件: $file echo 目录: $dir用shift的好处是无论参数顺序怎么变都能逐个处理不用写一大串复杂的索引逻辑。我在写通用脚本时几乎天天用属于那种会了之后离不开的技能。2.3 for循环与流程控制让脚本真正自动化起来没有循环和判断的脚本顶多算多条命令的合集。加上流程控制它才配叫编程。for循环是Shell里使用频率最高的循环常见三种写法# 写法1基于列表 for name in nginx redis mysql do echo 服务: $name done # 写法2基于范围Bash支持数字序列 for i in {1..10} do echo 第 $i 次 done # 写法3C语言风格 for ((i1; i10; i)) do echo 数值: $i done第一种最常用特别适合遍历文件列表。之前说的批量重命名核心就是它for f in *.txt do mv $f ${f%.txt}.bak done第二种的{1..10}很方便但如果数字很大或者需要更复杂的步长就建议用第三种C风格写法性能更好、可控性更强。while循环常用于需要持续读入的场景。比如逐行读取文件while IFS read -r line do echo 内容: $line done /etc/hosts注意这里的IFS read -r是固定搭配-r防止反斜杠被转义IFS保证行首行尾的空格不被吃掉。这行代码本身有点抽象你直接当成安全逐行读文件的模板背下来就行。if判断则是所有逻辑的地基if [ -f $1 ] then echo $1 是一个文件 elif [ -d $1 ] then echo $1 是一个目录 else echo $1 不知道是什么 fi判断文件类型的-f、-d、-e这些选项要重点记日常判断文件、目录、是否存在全靠它们。另外用单中括号[ ]时两边必须有空格[ $1 -f ]这种顺序错、空格错脚本就会报奇怪的错。推荐直接改用双中括号[[ ]]它支持更多的逻辑操作符比如、||、正则匹配~而且对空格宽容度高if [[ -f $1 $1 *.log ]] then echo 这是一个log文件 fi我个人的经验是所有新脚本一律用[[ ]]只有需要兼容老旧的sh环境时才用[ ]。3. 常用命令与脚本实战从重命名到巡检3.1 绕不开的高频命令清单写Shell脚本离不开系统命令。我按使用频率给你挑一份入门必会清单每一类挑最核心的讲文件与目录操作ls、cd、cp、mv、rm、mkdir、touch。这些是基本功重点注意rm -rf的危险性脚本里使用需要格外小心最好先加判断。文本处理三剑客grep、sed、awk。这才是Shell脚本里的重头戏。grep负责筛选行grep ERROR app.log能找出所有包含ERROR的行加-c统计行数加-v反向匹配加-E启用扩展正则。sed负责替换和编辑sed -i s/old/new/g file.conf是原地替换sed -n 20,30p file.log打印指定行范围。awk负责列处理和统计awk {print $1, $NF} access.log打印第一列和最后一列awk -F: {sum$3} END{print sum} /etc/passwd还能做求和统计。这三者配合起来能完成90%的文本处理需求。举一个综合场景统计一个日志文件里每个IP出现的次数awk {print $1} access.log | sort | uniq -c | sort -rn这条命令在真实排障中我用过无数次。它的思路是先取第一列IP排序去重并统计次数再从大到小排序。一跑出来后哪个IP访问最频繁一眼就知道。查询类find、xargs、du、df。find按时间、名称、大小找文件du -sh *看每个目录体积df -h看磁盘空间。它们结合起来可以实现很多自动化运维需求。进程与服务类ps、kill、systemctl。ps -ef | grep nginx查进程配合grep筛选systemctl status/restart/stop管理系统服务。写部署脚本时这些命令几乎必用。需要多说一句的是很多人在手机上可能见过adb shell这种写法——安卓调试里也有一个Shell环境但它的底层思想上和Linux Shell同源命令风格也很接近。如果你以后要写安卓自动化脚本现有Linux Shell基础同样能平移过去。不过我们这里先聚焦服务器场景毕竟那是Shell的主战场。3.2 脚本实战批量重命名文件讲再多理论知识不如完整写一个脚本。我选一个最常见的需求给一批文件统一加前缀或改后缀。假设目录里有photo1.jpg、photo2.jpg……一直到photo20.jpg我想把所有.jpg重命名为2026_photoN.jpg前面加上年份前缀。#!/bin/bash # rename.sh - 批量给jpg文件加前缀 for f in *.jpg do # 提取不带后缀的文件名 base${f%.jpg} # 新文件名 new_name2026_${base}.jpg # 如果已经改过名则跳过 if [[ $f 2026_* ]] then echo 跳过 $f已处理 continue fi mv $f $new_name echo 已重命名: $f - $new_name done脚本里几个点值得琢磨${f%.jpg}是Shell的变量模式删除语法%表示从右侧删除最短匹配这样可以把后缀剥掉。[[ $f 2026_* ]]用于判断是否已经是新名字避免重复跑脚本时二次加前缀。所有变量都加双引号防止文件名带空格导致执行出错。这个脚本看似简单但它的结构就是很多批量处理脚本的原型。你在它的基础上换成.png、.log、.conf或者改成删除特定前缀就是能直接用的工具。我自己通常还会再包一层if [ -f $f ]判断保证目录里没有匹配文件时不会直接报错。3.3 脚本实战5分钟写一个系统巡检脚本另一个高频需求是服务器巡检。每次登录服务器都要敲free看内存、敲df -h看磁盘太累了。写一个脚本把信息一次性打出来#!/bin/bash # check.sh - 系统健康快速巡检 echo 系统负载 uptime echo 内存使用 free -h echo 磁盘使用 df -h | grep -vE tmpfs|udev echo CPU占用TOP5 ps aux --sort-%cpu | head -6 echo 当前监听端口 ss -tlnp 2/dev/null | head -10这个脚本里的命令都是我在服务器上手敲频率最高的几类把它们合并到一个脚本之后登录机器只需要执行一次./check.sh所有关键信息一览无余省时又省心。你还可以搭配crontab实现定时巡检和告警。比如每天凌晨2点执行一次异常时把信息发到自己的邮箱或机器人。第一步很简单写一个凡是有问题就echo警告的脚本第二步再考虑接通知系统。在这些真实小项目上不断叠加功能你的Shell水平会比闷头看书涨得快得多。4. 踩坑与排查Shell编程的隐形陷阱4.1 空格与引号的战争Shell脚本报错里我见的第一个高频问题就是空格位置不对。它不是语法错误而是逻辑错误而且经常不报错只是结果不对。最经典的三个位置赋值等号两边不能有空格name zhangsan会尝试执行name命令。[ ]判断时括号内部要有空格[$1 a]会报错正确是[ $1 a ]。命令替换中的引号filename$(ls -la)里的$()和反引号都可以做命令替换但推荐用$()它支持嵌套、可读性也好。再强调一次引号。很多人看到mv $f $new_name不报错就放松了真遇到带空格的文件名才明白什么叫当场裂开。一句话在脚本里引用变量默认都加上双引号除非你明确知道要分词。这是全篇最值得记住的一条经验。4.2 退出码与条件判断的坑Shell里每个命令执行完都会留下一个退出码0表示成功非0表示失败。这个机制直接影响if的判断逻辑但新手常常被坑。坑点一if判断的是命令的退出码不是表达式的真假。if grep -q ERROR log.txt意思是如果grep成功找到就进入then分支。理解这一点你就能明白为什么if [ ... ]里的括号本质是一个有退出码的命令。坑点二脚本中最后一条命令的退出码决定脚本的退出状态。如果你在脚本最后执行了一条失败命令整个脚本的退出码就是非0这在CI流水线里会被判定为失败。解决办法之一是在脚本开头加set -e让任意命令失败时立刻退出。但set -e也有坑。如果你写cmd1 | cmd2管道中某一环失败时set -e不一定能抓住。想更严格可以配合set -o pipefail。但set -e会让某些预期内失败直接中断脚本比如grep没找到内容时返回非0如果不希望脚本退出需要加|| true。我的习惯是脚本前期调试用set -exx会打印每条执行的命令跑稳定后再把x去掉。坑点三$?只能取上一次命令的退出码。如果你先执行echo再判断$?取到的已经是echo的退出码了。要保存就得立刻赋值grep -q ERROR log.txt result$? # 后续可以放心使用 $result4.3 Shellcheck与调试技巧推荐排查Shell脚本问题光靠肉眼盯实在效率低。我强烈建议使用ShellCheck工具。它可以静态分析你的脚本找出变量引用问题、可能的引号错误、权限问题等。很多发行版的软件源里直接有装上后一条命令跑完就能看到你脚本里可能有哪几个坑对新手极其友好。执行方式很简单shellcheck myscript.sh它会输出类似SC2086: Double quote to prevent globbing and word splitting这样的提示新手可能看不懂英文说明但只要看到Double quote就知道该给变量加引号了。除了工具还有一个我自己经常用的笨办法用bash -x运行脚本。它会逐行打印脚本实际执行的命令和展开后的变量值一眼就能看出变量是不是为空、判断是不是走了错误分支。执行方式bash -x check.sh如果脚本很长输出太多你可以只在可疑的区域前后加set -x和set x把调试信息集中在局部。这个方法救了我不下几十次。5. 面试题与学习路线建议让别人看出你懂Shell5.1 面试常问的Shell考点解析很多做运维、后端、测试的朋友都会遇到Linux面试题Shell编程部分是面试官非常喜欢深挖的区域。我根据近几年被反复问的问题挑几个典型的说一说。问题1如何把一个目录下所有.log文件按大小排序后各取前几行内容典型回答find /path/logs -name *.log -exec ls -s {} \; | sort -rn | head -5 | awk {print $2} | xargs head这道题考的是命令组合能力。find负责定位sort负责排大小head取前5awk取文件名xargs将文件名传给head。整条命令一气呵成很能体现熟练度。问题2如何判断某个服务进程是否存在一种常见写法if pgrep -x nginx /dev/null then echo nginx正在运行 else echo nginx未运行 fi考的是你能不能跳出用ps硬grep然后用awk解析的野路子用pgrep这种专为场景设计的命令。同时/dev/null把不必要的输出丢了这也是一种好习惯。问题3写脚本统计access.log里各URL的访问次数并取前10。awk {print $7} access.log | sort | uniq -c | sort -rn | head -10第七列通常是URL路径Nginx默认格式剩下的模式跟之前统计IP一模一样。这个思路在面试时摆出来面试官基本能确认你是随手能写脚本的人。面试题不用背本质是检查你是否真的用Shell解决过问题。你日常写的脚本越多这类问题越答得来。5.2 从入门到进阶推荐的学习路径如果你是完全零基础我建议按照这个路径走节奏相对合理第一阶段Linux基础命令1-2周。把ls、cd、cp、mv、rm、grep、chmod这些高频命令练熟达到你想让电脑干什么能想到对应命令的水平。第二阶段Shell脚本语法2-3周。掌握变量、引号、$和$#、if、for、while、case。每天写一个10行动的小脚本比如批量创建用户、批量改扩展名。第三阶段文本处理三剑客3-4周。重点学grep、sed、awk配合正则表达式。建议拿真实日志练手比如统计访问最多的IP、筛选慢查询日志。第四阶段实战项目持续。找一个真实痛点写完整工具比如日志备份脚本、服务异常自动重启脚本。把之前学的东西串起来。不要急着看高深技巧Shell编程里真正决定水平的是你处理真实问题时的思路而思路只能从实际写脚本里获得。5.3 一点忠告别背命令背思路我在不少交流群里看到有人晒背过的命令清单说实话我不太建议那样子学Shell。命令是背不完的Linux里的命令成千上万每个命令参数又有一堆。真正有用的是解决问题的思路。同样面对找出日志错误并统计这个需求思路熟练的人脑子里会立刻浮现出先grep筛选再sort、uniq -c统计最后sort -rn排序。这个链条一旦形成用什么命令、带什么参数都是顺手的。如果思路不清楚就算你把awk所有参数都背下来看到实际问题还是不知道从哪里下手。我自己的做法是每遇到一个问题先想清楚我从原始数据走到目标结果中间需要做哪几步转换然后再逐步落实成命令。Shell脚本的写法不唯一但分解问题的能力是通用的。学会把大问题拆成几个小步骤这不仅是Shell编程的康庄大道也是所有编程领域的通用心法。最后再分享一个小习惯我会在个人电脑的笔记目录里放一个脚本工具箱文件夹每写一个能复用的脚本就丢进去并配上一句话说明注释。几个月下来你会拥有一套真正属于自己的Shell工具集碰到类似问题直接改造复用省下来的时间远超当初学习投入的时间。
阅读完成 · 觉得有帮助?
咨询建站