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逐步执行
- L1grep 打印 3,存进变量 errors。
- L2双引号里的 $errors 被换成 3。
errors today: 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"逐步执行
- L2notes/*.txt 展开成 ideas.txt 和 todo.txt,按字母顺序。
- L3
wc -l < 文件只打印数字,不带文件名。 - L5累加到总数里。
- 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查看答案
答案: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查看答案
答案:A
app.log 存在,而且是文件,不是文件夹。
动手练习
3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。
- 预测输出跟着脚本走
准确写出打印的内容。
- 改需求改成警告
脚本总是只打印数量。改成:错误多于 2 个时打印
WARN: 3 errors,否则打印OK: N errors。 - 从零写备份每一条笔记
建一个文件夹
backup。然后用for循环遍历notes/*.txt,把每个文件复制进backup/,并为每个文件打印saved 文件(文件就是循环变量,比如saved notes/ideas.txt)。
本课术语
| 术语 | 中文 | 英文定义 |
|---|---|---|
| Shell script | shell 脚本 | A file of shell commands run one after another. |
| Shell variable | shell 变量 | A name set with name=value and read with $name. |
| Exit status | 退出状态 | The number a command ends with: 0 means success. |