Shell 脚本入门:变量、条件判断与自动化任务一次讲清

举报
yd_220055865 发表于 2026/11/04 19:36:34 2026/11/04
【摘要】 对于刚接触 Linux 服务器的初学者来说,Shell 脚本是最值得先学会的自动化工具。它不需要安装额外的运行环境,不需要编译,只要把平时在终端里一条一条敲的命令写进一个文件,再给这个文件可执行权限,就能一遍遍重复执行。备份文件、清理日志、检查服务状态、批量改名,这些日常运维工作用 Shell 脚本都能写成几行到几十行的小程序。本文面向零基础读者,讲清楚 Shell 脚本的四个基本功:怎么写...

对于刚接触 Linux 服务器的初学者来说,Shell 脚本是最值得先学会的自动化工具。它不需要安装额外的运行环境,不需要编译,只要把平时在终端里一条一条敲的命令写进一个文件,再给这个文件可执行权限,就能一遍遍重复执行。备份文件、清理日志、检查服务状态、批量改名,这些日常运维工作用 Shell 脚本都能写成几行到几十行的小程序。

本文面向零基础读者,讲清楚 Shell 脚本的四个基本功:怎么写第一个脚本、变量怎么用、条件判断怎么写、循环和函数怎么组织,最后给出一个可以落地的日志清理脚本示例。文中示例均以 Bash 为准,这是绝大多数 Linux 发行版的默认 Shell。

一、第一个脚本:从 Hello World 到可执行文件

新建一个文件 hello.sh,写入下面三行:

#!/bin/bash
# 这是注释,以 # 开头,不会被执行
echo "Hello, Shell!"

第一行 #!/bin/bash 叫 Shebang,它告诉系统用哪个解释器来执行这个脚本。没有它,系统会用默认 Shell 执行,大多数情况下也能跑,但显式写出来更可靠、可移植。

让脚本可执行并运行它:

chmod +x hello.sh
./hello.sh

注意 ./hello.sh 前面的 ./ 不能省。当前目录通常不在系统的可执行文件搜索路径 PATH 里,直接写 hello.sh 系统会找不到文件。运行后终端输出 Hello, Shell!,第一个脚本就完成了。

一个好习惯是:脚本开头除了 Shebang,再写两行注释说明用途和作者日期。三个月后回头看,注释能帮你立刻想起这个脚本是干什么的。

二、变量:赋值不加空格,引用要加引号

Shell 变量的赋值语法很简单,但有一个新手最容易踩的坑:等号两边不能有空格。

name="linux"
echo $name
echo "欢迎使用 ${name} 服务器"

name=“linux” 是正确的,name = “linux” 会被解析成"执行一个叫 name 的命令",从而报错。引用变量时建议用双引号包裹:“$name”。不加引号时,如果变量值里有空格,Shell 会按空格把它拆成多个词,命令的行为就变了。

${name} 这种带花括号的写法在拼接字符串时尤其重要。写 echo “${name}server” 能明确区分变量名和后面的文字,而写 echo “$nameserver” 时,Shell 会去找一个叫 nameserver 的变量,结果是空。

常用的系统内置变量也值得记住:$HOME 是当前用户的主目录,$PWD 是当前工作目录,$USER 是当前用户名,$? 是上一条命令的退出状态码,0 表示成功,非零表示失败。写脚本时用 $? 判断上一条命令是否成功,是很常见的写法。

只读变量可以用 readonly 声明,环境变量用 export 导出给子进程。例如 export PATH=“$PATH:/opt/mybin” 就是把一个目录追加到可执行文件搜索路径里。注意,脚本里 export 的变量只对该脚本及其子进程有效,脚本退出后就失效了,不会永久改变系统环境。

三、条件判断:if、test 与方括号

Shell 的条件判断围绕 if 语句展开,基本结构是:

if [ -f "/var/log/app.log" ]; then
    echo "日志文件存在"
else
    echo "日志文件不存在"
fi

这里的方括号 [ ] 实际上是一个命令(test 命令的简写),方括号两边必须留空格,[-f 或 ] 前面不留空格都会报错。常用的判断条件有:

  • -f 文件:文件存在且是普通文件
  • -d 目录:目录存在
  • -z 字符串:字符串为空
  • -n 字符串:字符串非空
  • 字符串比较:= 相等,!= 不相等
  • 数字比较:-eq 等于,-ne 不等于,-gt 大于,-lt 小于,-ge 大于等于,-le 小于等于

数字比较和字符串比较不能混用,这是第二个常见坑。判断端口号、文件数量这类数字要用 -eq、-gt;判断用户名、文件路径这类字符串要用 =、!=。用 = 去比两个数字在某些情况下也能"碰巧"工作,但语义不对,写脚本时应当分清。

多条件组合可以用 &&(并且)和 ||(或者),也可以用 elif 写多分支:

read -p "请输入一个数字: " num
if [ "$num" -gt 100 ]; then
    echo "大于 100"
elif [ "$num" -gt 50 ]; then
    echo "大于 50,小于等于 100"
else
    echo "小于等于 50"
fi

read -p 会在终端提示用户输入并把输入存入变量。交互式脚本里常用它,但自动化脚本应当尽量避免交互,改用命令行参数。脚本的命令行参数用 $1、$2 表示第一个、第二个参数,$# 表示参数个数,$@ 表示全部参数。写脚本时先检查 $# 是否符合预期,参数不对就打印用法说明并退出,能省下很多调试时间。

四、循环与函数:把重复劳动交给机器

循环解决"同一件事做很多遍"的问题。for 循环遍历列表,while 循环在条件成立时一直执行:

# 遍历目录下的所有 .log 文件
for file in /var/log/*.log; do
    echo "正在处理 $file"
done

# 计数循环
count=1
while [ "$count" -le 5 ]; do
    echo "第 $count 次"
    count=$((count + 1))
done

$((count + 1)) 是算术扩展的写法,Shell 里做整数运算就用它。注意 for file in /var/log/*.log 里如果目录下没有任何 .log 文件,通配符可能原样保留而不展开,处理重要文件前先判断文件是否存在更稳妥。

函数把一段逻辑封装成可复用的单元:

check_service() {
    if systemctl is-active --quiet "$1"; then
        echo "$1 运行正常"
    else
        echo "$1 未运行"
    fi
}

check_service nginx
check_service mysql

函数定义用 函数名() { …; },调用时直接写函数名加参数,函数内部用 $1 取第一个参数。把检查、备份、清理这类逻辑写成函数,主流程就会变得非常清晰,也方便以后复用。

五、实战:一个日志清理脚本

把前面讲的知识点拼起来,可以写一个实用的日志清理脚本:删除指定目录下 7 天前、后缀为 .log 的文件,删除前先打印要删的文件,执行后汇报删除结果:

#!/bin/bash
# 用途:清理 /var/log/myapp 下 7 天前的日志文件
# 注意:请先把 LOG_DIR 改成你自己的目录再运行

LOG_DIR="/var/log/myapp"
DAYS=7

if [ ! -d "$LOG_DIR" ]; then
    echo "目录不存在: $LOG_DIR"
    exit 1
fi

echo "正在清理 $LOG_DIR 下 ${DAYS} 天前的 .log 文件..."
find "$LOG_DIR" -name "*.log" -type f -mtime +$DAYS -print -delete

if [ $? -eq 0 ]; then
    echo "清理完成"
else
    echo "清理过程中出现错误,请检查权限"
    exit 1
fi

这个脚本有几个值得注意的设计。第一,开头先判断目录是否存在,不存在就报错退出,而不是让 find 在一个不存在的目录上静默失败。第二,find 的 -print -delete 组合会先打印再删除,日志里留下了删除记录,出问题可以追溯。第三,用 $? 判断 find 是否成功,失败时给出明确提示并以非零状态码退出,方便被其他自动化工具(如定时任务)感知到失败。

真正跑清理、删除类脚本之前,务必先在测试目录里试一遍,或者先把 -delete 换成只打印,确认要删的文件列表无误后再加回删除动作。删除操作不可逆,多一层确认永远不亏。

六、调试与定时:让脚本真正跑起来

脚本出问题时,在 Shebang 后加 -x 可以开启调试模式:把 #!/bin/bash 改成 #!/bin/bash -x,执行时 Shell 会把每一条命令连同展开后的参数都打印出来,变量值不对、条件判断走错分支,一眼就能看出来。也可以只对某一段开启调试:set -x 开启,set +x 关闭。

脚本写好后,可以用 cron 让它定时执行。执行 crontab -e,加上一行:

0 3 * * * /home/user/clean_logs.sh >> /var/log/clean_logs.log 2>&1

这表示每天凌晨 3 点执行一次,输出重定向到日志文件。cron 环境里的 PATH 比交互终端小,脚本里用到的命令建议写绝对路径,或者在脚本开头显式设置 PATH,否则可能出现"终端能跑、定时任务跑不了"的情况。

七、常见错误清单

最后总结新手最容易犯的几个错误,写脚本时可以逐项自查:赋值等号两边加了空格;方括号两边没留空格;变量引用没加引号导致空格拆词;数字比较用了 =、字符串比较用了 -eq;当前目录脚本没加 ./ 就执行;删除、覆盖类操作没先在测试目录验证。把这张清单贴在手边,能避开 Shell 入门阶段的大多数坑。

Shell 脚本的价值不在于语法多优雅,而在于把重复劳动变成一次写好、反复运行的工具。从今天的第一个 hello.sh 开始,遇到第二次要做的重复操作,就试着把它写成脚本。几次下来,你会发现服务器运维的大部分体力活,都可以交给几十行脚本安静地完成。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。