先搞懂Bash脚本的基础逻辑
写Bash脚本不是“写代码”,更像“把命令行的操作串起来”——但得先搞懂几个核心规则,否则脚本要么跑不起来,要么出奇怪的错。

首先是shebang(#!),它得放在脚本第一行,告诉系统“用哪个解释器执行这个脚本”。比如#!/bin/bash
是最常用的,没这行的话,系统可能会用默认的sh解释器,导致某些Bash特有的语法失效。
然后是变量,和命令行里用的变量差不多,但脚本里要注意“展开”的问题:双引号会保留变量的值(比如echo "$HOME"
会输出/home/yourname
),单引号则会原样输出(echo '$HOME'
就是$HOME
)。举个例子,如果你要处理带空格的文件名,必须用双引号包着变量,比如mv "$old_file" "$new_file"
,否则系统会把空格当成分隔符,把文件名拆成多个参数。
还有条件判断,比如判断文件是否存在:
#!/bin/bash
if [ -f "log.txt" ]; then
echo "日志文件存在,开始分析"
else
echo "日志文件不存在,退出"
exit 1
fi
这里的-f
是“是否为普通文件”的测试条件,类似的还有-d
(目录)、-x
(可执行文件),记不住的话输man test
看手册,比背口诀管用。
用命令行工具搭脚本的“积木”
Bash脚本的威力,在于把Linux自带的命令行工具拼成“解决问题的链条”。比如grep
(找文本)、awk
(处理文本)、find
(找文件)、sed
(改文本),这些工具就是脚本里的“积木”,单独用能解决小问题,串起来能解决大问题。
先看个文件批量重命名的例子——如果你有100张.jpg
照片,想改成20250824_1.jpg
、20250824_2.jpg
这样的格式,手动改要疯,写个脚本5秒搞定:
#!/bin/bash
# 批量重命名.jpg文件为“日期_序号.jpg”
date=$(date +%Y%m%d) # 获取今天的日期,格式如20250824
count=1 # 初始化序号
for file in *.jpg; do # 遍历当前目录下的所有.jpg文件
mv "$file" "${date}_${count}.jpg" # 重命名
count=$((count+1)) # 序号加1
done
这里用了date
命令获取日期,for
循环遍历文件,mv
命令重命名——都是命令行里常用的工具,串起来就成了有用的脚本。
再比如日志分析,假设你要从Nginx日志里找出访问最多的前10个IP,用grep
+awk
+sort
就能搞定:
#!/bin/bash
# 分析Nginx访问日志,输出Top10 IP
log_file="/var/log/nginx/access.log"
# 用grep提取IP(假设日志格式是“IP - - [时间]...”)
# 用awk取第一列(IP列),sort排序,uniq统计次数,再sort倒序,head取前10
grep -oE "([0-9]{1,3}.){3}[0-9]{1,3}" "$log_file" |
awk '{print $1}' |
sort |
uniq -c |
sort -nr |
head -n 10
解释下:grep -oE
用正则提取IP,awk '{print $1}'
取第一列(因为grep输出的只有IP),sort
把相同的IP排到一起,uniq -c
统计每个IP出现的次数,sort -nr
按次数倒序,最后head -n 10
取前10。
写一个能解决实际问题的脚本
光看例子不够,得自己写一个“能用上”的脚本。比如清理旧日志——很多服务器的日志会越积越大,写个脚本每天删7天前的日志:
#!/bin/bash
# 清理/var/log下7天前的.log文件
log_dir="/var/log"
# 找所有.log文件,修改时间超过7天,执行删除
find "$log_dir" -type f -name "*.log" -mtime +7 -exec rm -f {} ;
# 输出清理结果
echo "已清理$(find "$log_dir" -type f -name "*.log" -mtime +7 | wc -l)个旧日志文件"
这里的-type f
指定找普通文件,-mtime +7
是“修改时间超过7天”,-exec rm -f {} ;
是对找到的每个文件执行删除(-f
避免因为文件不存在报错)。最后用wc -l
统计清理的文件数,让你知道脚本干了啥。
调试脚本的小技巧
写脚本总会遇到“跑不起来”的情况,别慌,用这几个小技巧快速定位问题:
-
加
set -x
看执行过程:在脚本开头加set -x
,系统会输出每一步执行的命令和参数,比如:#!/bin/bash set -x # 开启调试模式 date=$(date +%Y%m%d) echo "今天的日期是$date"
执行后会输出:
+ date=20250824
、+ echo '今天的日期是20250824'
,能清楚看到变量的值对不对。 -
用
echo
输出中间变量:如果脚本没按预期执行,在关键步骤加echo
,比如遍历文件时输出文件名:for file in *.jpg; do echo "正在处理文件:$file" # 输出当前处理的文件 mv "$file" "${date}_${count}.jpg" count=$((count+1)) done
这样就能知道脚本是不是真的遍历到了所有文件。
-
用
bash -n
检查语法错误:在执行脚本前,先用bash -n script.sh
检查语法,比如漏了fi
或者done
,系统会直接告诉你哪里错了,比跑起来再报错高效。
自动化任务的进阶玩法
脚本写好后,别手动执行——用cron把它变成定时任务,比如每天凌晨1点清理日志:
1. 输crontab -e
打开定时任务编辑器;
2. 加一行:0 1 * * * /home/yourname/scripts/clean_log.sh
;
3. 保存退出,cron会自动生效。
解释下cron的格式:分 时 日 月 周
,比如0 1 * * *
就是“每天1点0分执行”。如果想每周日执行,就改成0 1 * * 0
(周日是0或7)。
还有at命令,用来执行一次性任务,比如“明天下午3点执行备份脚本”:
at 15:00 tomorrow -f /home/yourname/scripts/backup.sh
输atq
能看等待执行的任务,atrm 任务号
能取消任务。
最后说个小提醒:脚本写好后,一定要加执行权限,用chmod +x script.sh
,否则系统会提示“权限不够”。另外,把常用的脚本放到~/scripts
目录,再把这个目录加到PATH
里(echo 'export PATH=$PATH:~/scripts' >> ~/.bashrc
),以后直接输脚本名就能执行,不用打全路径。
其实Bash脚本没那么难——本质就是“把你在命令行里做的事,写成能重复执行的流程”。多写几个解决自己问题的脚本,比如批量转换图片格式、监控磁盘空间,你会发现Linux命令行越来越“听话”,自己的工作效率也越来越高。
原创文章,作者:,如若转载,请注明出处:https://zube.cn/archives/268