自动化脚本怎么写才不翻车?新手避坑指南来了
大家好,我是一名从培训班出来的前端开发者。记得刚入行那会儿,每天被各种重复任务折磨得够呛:改配置、批量重命名、自动部署……老板还总说“能不能搞个脚本来自动化一下?”我一脸懵——脚本是啥?怎么写?写了会不会删库跑路?
后来我花了不少时间摸索,踩了无数坑,终于搞明白了自动化脚本的核心逻辑。今天我就用最接地气的方式,带零基础的你从零开始写出安全、高效、可维护的自动化脚本。这篇文章不讲虚的,全是实战干货,尤其会重点解决新手最头疼的两个问题:资源管理不当导致系统卡死,以及运营流程混乱引发线上事故。
一、自动化脚本到底是什么?
简单说,自动化脚本就是让电脑替你干重复、枯燥的活。
比如:
- 每天早上8点自动备份数据库
- 批量压缩1000张图片
- 发布新版本时自动构建、测试、部署
- 定时清理服务器上的临时文件
这些事如果手动做,又慢又容易出错。而脚本一旦写好,就能一键执行,甚至定时自动跑。
💡 我当初学的时候,以为脚本就是写一堆命令堆在一起。结果第一次写的脚本没加错误判断,不小心把生产环境的配置文件给覆盖了……还好有备份!从此我明白:写脚本不是图快,而是图稳。
二、环境准备:5分钟搭好开发环境
我们用 Node.js + JavaScript 来写脚本(因为前端同学都熟悉,而且生态强大)。如果你还没装 Node,请按以下步骤操作:
1. 安装 Node.js
- 访问 https://nodejs.org
- 下载 LTS 版本(长期支持版,更稳定)
- 安装时一路默认选项即可
2. 验证安装
打开终端(Mac/Linux 用 Terminal,Windows 用 PowerShell 或 CMD),输入:
node -v
npm -v
如果显示版本号(如 v18.17.0),说明安装成功!
3. 创建项目目录
mkdir my-auto-script
cd my-auto-script
npm init -y
这会在当前目录生成一个 package.json 文件,用于管理脚本依赖。
三、核心概念:资源与运营的平衡术
很多新手写脚本只关注“功能实现”,却忽略了两个致命问题:
📌 什么是“资源”?
在脚本中,“资源”指的是:
- 内存
- CPU 使用率
- 磁盘 I/O(读写速度)
- 网络带宽
- 文件句柄(打开的文件数量)
错误示范:一次性读取10GB的日志文件到内存 → 内存爆了,系统卡死!
正确做法:用流式读取(Stream),一次只处理一小块数据。
📌 什么是“运营”?
“运营”在这里指脚本的可维护性、可观测性和可恢复性,包括:
- 日志记录(方便排查问题)
- 错误处理(出错了别直接崩)
- 参数配置(不同环境能灵活切换)
- 回滚机制(万一出错能快速恢复)
✅ 最佳实践口诀:
小步快跑,资源节制;日志齐全,运营无忧。
四、实战:写一个安全的文件清理脚本
我们来做一个实用场景:自动清理30天前的临时文件。
步骤1:安装必要工具
npm install fs-extra chalk dayjs
fs-extra:增强版文件操作库(比原生 fs 更友好)chalk:给控制台输出加颜色(方便区分信息/警告/错误)dayjs:轻量级日期处理库
步骤2:编写脚本 clean-temp.js
// clean-temp.js
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const dayjs = require('dayjs');
// 配置项(方便后续调整)
const CONFIG = {
TEMP_DIR: './temp', // 临时文件目录
DAYS_TO_KEEP: 30, // 保留最近30天的文件
MAX_CONCURRENT: 5, // 最大并发数(控制资源占用!)
};
async function cleanTempFiles() {
console.log(chalk.blue('🚀 开始清理临时文件...'));
try {
// 1. 检查目录是否存在
if (!await fs.pathExists(CONFIG.TEMP_DIR)) {
console.log(chalk.yellow('⚠️ 临时目录不存在,跳过清理'));
return;
}
// 2. 获取所有文件
const files = await fs.readdir(CONFIG.TEMP_DIR);
if (files.length === 0) {
console.log(chalk.green('✅ 临时目录为空,无需清理'));
return;
}
// 3. 过滤出需要删除的旧文件
const cutoffDate = dayjs().subtract(CONFIG.DAYS_TO_KEEP, 'day');
const filesToDelete = [];
for (const file of files) {
const filePath = path.join(CONFIG.TEMP_DIR, file);
const stats = await fs.stat(filePath);
// 跳过目录(只处理文件)
if (stats.isDirectory()) continue;
// 判断是否超过保留天数
if (dayjs(stats.mtime).isBefore(cutoffDate)) {
filesToDelete.push(filePath);
}
}
// 4. 安全删除(限制并发,避免资源耗尽)
if (filesToDelete.length === 0) {
console.log(chalk.green('✅ 没有需要清理的旧文件'));
return;
}
console.log(chalk.yellow(`🗑️ 共发现 ${filesToDelete.length} 个旧文件,开始删除...`));
// 分批删除,控制并发
const batches = [];
for (let i = 0; i < filesToDelete.length; i += CONFIG.MAX_CONCURRENT) {
batches.push(filesToDelete.slice(i, i + CONFIG.MAX_CONCURRENT));
}
for (const batch of batches) {
await Promise.all(
batch.map(async (filePath) => {
try {
await fs.remove(filePath);
console.log(chalk.gray(` 已删除: ${filePath}`));
} catch (err) {
console.error(chalk.red(` 删除失败: ${filePath} - ${err.message}`));
}
})
);
// 每批之间稍作休息,降低系统压力
await new Promise(resolve => setTimeout(resolve, 100));
}
console.log(chalk.green('✅ 清理完成!'));
} catch (error) {
console.error(chalk.red('❌ 清理过程中发生错误:'), error.message);
// 运营关键:错误也要记录到日志文件!
await fs.appendFile('cleanup-error.log', `${new Date().toISOString()} - ${error.stack}\n`);
}
}
// 执行脚本
cleanTempFiles();
步骤3:测试脚本
- 创建测试目录:
mkdir temp
echo "test" > temp/file1.txt
touch -d "2020-01-01" temp/old-file.txt # Linux/Mac 创建旧文件
- 运行脚本:
node clean-temp.js
你会看到彩色输出,并且只有旧文件被删除!
五、新手常犯的5个致命错误(附解决方案)
| 错误 | 后果 | 解决方案 |
|---|---|---|
| 不加错误处理 | 脚本崩溃,任务中断 | 用 try/catch 包裹主逻辑 |
| 一次性加载大量数据 | 内存溢出,系统卡死 | 使用流(Stream)或分页处理 |
| 硬编码路径/参数 | 不同环境无法复用 | 把配置抽成 CONFIG 对象 |
| 没有日志记录 | 出问题无法排查 | 至少记录关键步骤和错误 |
| 权限过高 | 误删重要文件 | 脚本只操作指定目录,避免用 root 运行 |
🛑 血泪教训:我见过同事写了个
rm -rf /tmp/*的 shell 脚本,结果手抖写成rm -rf / tmp/*(多了个空格)……整个系统根目录被清空!所以永远不要在脚本里写危险命令而不加确认。
六、进阶建议:让你的脚本更专业
1. 加上命令行参数
用 process.argv 或 minimist 库支持动态传参:
node clean-temp.js --days=7 --dir=/var/log
2. 添加定时任务(Cron)
Linux/Mac 用 crontab -e 添加:
# 每天凌晨2点执行
0 2 * * * cd /your/script/path && node clean-temp.js >> cleanup.log 2>&1
3. 输出结构化日志
把日志写成 JSON 格式,方便后续分析:
{"time":"2023-10-01T02:00:00Z","action":"delete","file":"/temp/old.log","status":"success"}
4. 单元测试不能少
用 Jest 写简单测试,确保逻辑正确:
test('should not delete recent files', async () => {
// 创建一个1天前的文件
// 运行脚本
// 断言文件仍然存在
});
七、下一步学什么?
如果你已经掌握了基础脚本编写,建议按以下路径深入:
- 学 Shell 脚本:Linux 系统运维必备(
bash/zsh) - 掌握任务调度:了解
cron、systemd timer、Airflow 等工具 - 学习 CI/CD:把脚本集成到 GitLab CI / GitHub Actions 中
- 探索自动化框架:如 Python 的
schedule、Node.js 的node-cron
💬 最后送大家一句话:自动化不是为了替代人,而是让人去做更有价值的事。写好每一个脚本,都是在为未来的自己节省时间。
现在,打开你的终端,新建一个 .js 文件,写下你的第一行自动化代码吧!遇到问题随时回来翻这篇指南——毕竟,我也是这么一步步走过来的。

评论 0