人人都能学编程
English 开始学习
核心 · Linux第 6 课 / 共 6 课免费阅读

shell 脚本 · Linux 与命令行

怎么把重复敲的命令变成脚本?

课程目录

为什么需要它

如果你每天早上都敲同样的五条命令,脚本可以替你敲,而且每次都一模一样。真实服务器上的部署脚本、备份和健康检查,大多是用你已经会的命令,加上变量、条件和循环写成的小 shell 脚本。

直觉理解

  • 变量:name=ada(= 两边不能有空格),用的时候写 $name。
  • 命令结果:n=$(grep -c ERROR logs/app.log) 把命令打印的内容存起来。
  • 算术:$((n + 1))。
  • 条件:if [ $n -gt 2 ]; then … else … fi。比较数字用 -eq -ne -gt -lt -ge -le,检查文件用 -f(文件存在)和 -d(文件夹存在)。
  • 循环:for f in logs/*.log; do … done。

变量里可能有空格时,写成 "$var",加上双引号。

定义

命令替换

`$(command)` runs the command and puts what it printed in its place, so you can store it in a variable.
`$(命令)` 运行这个命令,用它打印的内容替换自己,这样就能存进变量里。

退出状态

Every command reports 0 for success and another number for failure. `if` runs the then-part when the test reports 0.
每条命令结束时都会报告一个数:0 表示成功,其他数表示失败。`if` 在检测结果为 0 时执行 then 部分。

示例

一个健康检查

在互动课里运行

数一数错误,再决定说什么。

errors=$(grep -c ERROR logs/app.log)
echo "errors today: $errors"
if [ $errors -gt 2 ]; then
    echo "ALERT: too many errors"
else
    echo "all fine"
fi
逐步执行
  1. L1grep 打印 3,存进变量 errors。
  2. L2双引号里的 $errors 被换成 3。errors today: 3
  3. L33 -gt 2 成立,所以执行 then 部分。ALERT: too many errors

对 notes 里的每个文本文件,打印名字和行数。用一个计数器把它们加起来。

total=0
for f in notes/*.txt; do
    n=$(wc -l < $f)
    echo "$f: $n"
    total=$((total + n))
done
echo "total: $total"
逐步执行
  1. L2notes/*.txt 展开成 ideas.txt 和 todo.txt,按字母顺序。
  2. L3wc -l < 文件 只打印数字,不带文件名。
  3. L5累加到总数里。
  4. L73 + 3。total: 6

常见错误

= 两边有空格

n = 3 会去运行一个叫 n 的命令。要写 n=3。

[ ] 里少了空格

[$n -gt 2] 会出错;方括号里外都要有空格:[ $n -gt 2 ]。

小测验

1. 这段代码会输出什么?

n=0
for w in red green blue; do
    n=$((n + 1))
    echo "$n $w"
done
  1. A
    1 red
    2 green
    3 blue
  2. B
    0 red
    1 green
    2 blue
  3. C
    1 red
    1 green
    1 blue
查看答案

答案:A

每次 echo 之前 n 都加 1。

2. 这段代码会输出什么?

if [ -f logs/app.log ]; then echo found; else echo missing; fi
if [ -d logs/app.log ]; then echo folder; else echo "not a folder"; fi
  1. A
    found
    not a folder
  2. B
    found
    folder
  3. C
    missing
    not a folder
查看答案

答案:A

app.log 存在,而且是文件,不是文件夹。

动手练习

3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。

  1. 预测输出跟着脚本走

    准确写出打印的内容。

  2. 改需求改成警告

    脚本总是只打印数量。改成:错误多于 2 个时打印 WARN: 3 errors,否则打印 OK: N errors。

  3. 从零写备份每一条笔记

    建一个文件夹 backup。然后用 for 循环遍历 notes/*.txt,把每个文件复制进 backup/,并为每个文件打印 saved 文件(文件就是循环变量,比如 saved notes/ideas.txt)。

在互动课里练这一课

打开互动课,这些例子都能直接改、直接运行,练习题提交马上判题。免费开始,不用注册。

互动课按顺序解锁:前面的课还没学,会先带你到课程地图。

本课术语

术语中文英文定义
Shell scriptshell 脚本A file of shell commands run one after another.
Shell variableshell 变量A name set with name=value and read with $name.
Exit status退出状态The number a command ends with: 0 means success.