上一期回顾
上回说到,我们给小龙虾安装了各种技能包,让它从一只普通的虾变成了一只多才多艺的小助手。
今天,我们来聊聊养殖小龙虾最重要的事情:安全。
灵魂拷问:你的小龙虾安全吗?
养过宠物的人都知道,最可怕的事情不是宠物不听话,而是宠物走丢或者被坏人偷走。
OpenClaw 也是如此。如果不注意安全:
🔓 服务器被入侵,数据泄露
🤖 AI 被恶意诱导,说出不该说的话
💰 工具被滥用,产生意外费用
📴 服务突然宕机,业务中断
所以,今天我们就来给小龙虾装上门锁、加固体质、自动巡检、让它自己发现问题自己处理。
一、安全加固:给小龙虾装上门锁
1.1 为什么要加固?
小龙虾虽然聪明,但它毕竟是一只虾——不会自己判断危险。
举几个例子:
有人问你服务器密码,小龙虾可能会直接回答
有人发送恶意链接,小龙虾可能会帮你点击
有人想让小龙虾删库跑路,小龙虾可能会执行
所以我们需要安全策略来限制它的行为。
1.2 配置文件介绍
OpenClaw 的安全配置在 ~/.openclaw/config.yml 中:
security:
# 允许执行的命令白名单
allowCommands:
- git
- npm
- node
- python
# 禁止执行的命令黑名单
denyCommands:
- rm -rf /
- drop database
- shutdown
# 是否允许外部网络请求
allowExternalRequests: true
# 是否允许执行 Shell 命令
allowShellExec: true
# 权限级别
permissions:
# 初级模式:只允许安全的只读操作
level: "read-only"
# 中级模式:允许执行预定义的工具
# 高级模式:允许执行任意命令(危险!)
# level: "full"
1.3 推荐的安全配置
入门级(新手推荐):
security:
allowCommands:
- git
- npm
- node
- python
- curl
denyCommands:
- rm -rf /
- mkfs
- shutdown
allowExternalRequests: true
allowShellExec: false # 关闭 Shell 执行,更安全
进阶级(有经验者):
security:
allowCommands:
- git
- npm
- node
- python
- docker
- systemctl
denyCommands:
- rm -rf / --no-preserve-root
- init 0
- init 6
allowExternalRequests: true
allowShellExec: true
maxExecTimeout: 300 # 单次命令最长 5 分钟
1.4 SSH 密钥管理
如果你的 OpenClaw 需要连接远程服务器,一定要用 SSH 密钥而不是密码:
# 1. 生成 SSH 密钥
ssh-keygen -t ed25519 -C"openclaw@your-server"
# 2. 把公钥复制到服务器
ssh-copy-id -i ~/.ssh/openclaw.pub user@your-server
# 3. 配置 SSH 客户端使用这个密钥
cat >> ~/.ssh/config <<EOF
Host openclaw-server
HostName your-server.com
User admin
IdentityFile ~/.ssh/openclaw
IdentitiesOnly yes
EOF
1.5 环境变量保密
敏感信息(如 API Key、密码)不要写在代码里,要放在环境变量中:
# 在 ~/.bashrc 或 ~/.zshrc 中添加
exportOPENAI_API_KEY="sk-xxxxx"
exportFEISHU_APP_ID="cli_xxxxx"
exportFEISHU_APP_SECRET="xxxxx"
然后在代码中这样使用:
constapiKey=process.env.OPENAI_API_KEY;
if (!apiKey) {
console.error("❌ 请设置 OPENAI_API_KEY 环境变量");
process.exit(1);
}
二、自动化巡检:让小龙虾每天自己巡检
2.1 什么是自动化巡检?
想象你有一个员工,每天自动检查服务器状态、监控指标、磁盘空间——发现问题就报警,不需要你操心。
这就是自动化巡检。
2.2 使用 Cron 定时任务
Linux 的 cron 可以让小龙虾自动执行任务:
# 编辑定时任务
crontab -e
# 添加以下任务:
# 每小时检查一次服务器状态
0 * * * * cd ~/.openclaw && node scripts/health-check.js
# 每天早上 9 点巡检(北京时间)
01 * * * cd ~/.openclaw && node scripts/daily-inspection.js # UTC 1点 = 北京 9点
# 每周一早上 9 点生成周报
01 * * 1cd ~/.openclaw && node scripts/weekly-report.js
2.3 巡检脚本示例
// scripts/health-check.js
const { execSync } =require('child_process');
constaxios=require('axios');
asyncfunctionhealthCheck() {
console.log("🔍 开始巡检...");
constresults= {
cpu: awaitcheckCPU(),
memory: awaitcheckMemory(),
disk: awaitcheckDisk(),
services: awaitcheckServices()
};
// 如果有问题,发送报警
if (results.cpu>90||results.disk>85) {
awaitsendAlert("⚠️ 服务器状态异常!", results);
}
console.log("✅ 巡检完成");
console.log(JSON.stringify(results, null, 2));
}
asyncfunctioncheckCPU() {
// 使用 top 命令获取 CPU 使用率
constoutput=execSync("top -bn1 | grep 'Cpu(s)' | awk '{print $2}'").toString();
returnparseFloat(output);
}
asyncfunctioncheckMemory() {
constoutput=execSync("free -m | grep Mem | awk '{print $3/$2 * 100}'").toString();
returnparseFloat(output);
}
asyncfunctioncheckDisk() {
constoutput=execSync("df -h / | tail -1 | awk '{print $5}' | sed 's/%//'").toString();
returnparseFloat(output);
}
asyncfunctioncheckServices() {
constservices= ["docker", "redis", "mysql"];
constresults= {};
for (constsvcofservices) {
try {
execSync(`systemctl is-active ${svc}`, { stdio: 'ignore' });
results[svc] ="✅ 运行中";
} catch {
results[svc] ="❌ 已停止";
}
}
returnresults;
}
asyncfunctionsendAlert(message, data) {
// 这里可以接入飞书机器人、邮件等报警渠道
console.error("🚨 报警:", message, data);
}
healthCheck().catch(console.error);
2.4 巡检报告样例
运行巡检后,你会收到这样的报告:
🦞 小龙虾自动巡检报告
时间: 2026-04-02 10:00:00
【服务器状态】
| 指标 | 状态 | 值 |
|------|------|-----|
| CPU | ✅ 正常 | 35.2% |
| 内存 | ⚠️ 偏高 | 78.5% |
| 磁盘 | ✅ 正常 | 62.1% |
【服务状态】
| 服务 | 状态 |
|------|------|
| Docker | ✅ 运行中 |
| Redis | ✅ 运行中 |
| MySQL | ❌ 已停止 |
【建议】
内存使用率偏高,建议关注。
MySQL 服务已停止,请立即检查!
三、故障自愈:让小龙虾自己发现问题自己处理
3.1 什么是故障自愈?
想象你的小龙虾不仅能发现问题,还能自动解决问题:
Redis 挂了 → 自动重启
磁盘满了 → 自动清理旧日志
服务超时 → 自动重试
这就是故障自愈。
3.2 常见故障处理策略
策略一:自动重启服务
asyncfunctionautoRestart(service) {
console.log(`🔄 尝试重启 ${service}...`);
try {
// 先停止服务
execSync(`systemctl stop ${service}`, { stdio: 'ignore' });
awaitsleep(2000);
// 再启动服务
execSync(`systemctl start ${service}`);
// 检查是否启动成功
constisActive=execSync(`systemctl is-active ${service}`).toString().trim();
if (isActive==='active') {
console.log(`✅ ${service}重启成功`);
returntrue;
}
} catch (e) {
console.error(`❌ ${service}重启失败:`, e.message);
}
returnfalse;
}
策略二:清理磁盘空间
asyncfunctioncleanupDisk() {
console.log("🧹 开始清理磁盘...");
// 清理旧日志(保留最近 7 天)
execSync(`find /var/log -name "*.log" -mtime +7 -delete`);
// 清理 Docker 临时文件
execSync("docker system prune -f");
// 清理 npm 缓存
execSync("npm cache clean --force");
// 清理旧的 core dump 文件
execSync(`find / -name "core.*" -mtime +1 -delete 2>/dev/null`);
console.log("✅ 清理完成");
}
策略三:自动扩容
asyncfunctionautoScale() {
// 检查当前负载
constcpu=awaitcheckCPU();
constmemory=awaitcheckMemory();
if (cpu>80||memory>85) {
console.log("📈 负载过高,尝试扩容...");
// 这里是伪代码,实际需要根据你的基础设施来写
execSync("docker-compose up -d --scale app=3");
console.log("✅ 已扩容,当前实例数: 3");
}
}
3.3 自愈编排示例
// scripts/self-healing.js
classSelfHealing {
constructor() {
this.strategies= [
{ name: "redis", check: this.checkRedis, fix: () =>this.autoRestart("redis") },
{ name: "docker", check: this.checkDocker, fix: () =>this.autoRestart("docker") },
{ name: "disk", check: this.checkDisk, fix: this.cleanupDisk },
];
}
asyncrun() {
console.log("🔧 开始故障自愈检查...");
for (conststrategyofthis.strategies) {
constisHealthy=awaitstrategy.check();
if (!isHealthy) {
console.log(`⚠️ ${strategy.name}状态异常,尝试自愈...`);
awaitstrategy.fix();
} else {
console.log(`✅ ${strategy.name}状态正常`);
}
}
console.log("🔧 自愈检查完成");
}
asynccheckRedis() {
try {
execSync("redis-cli ping", { stdio: 'ignore' });
returntrue;
} catch {
returnfalse;
}
}
asynccheckDocker() {
try {
execSync("docker info", { stdio: 'ignore' });
returntrue;
} catch {
returnfalse;
}
}
asynccheckDisk() {
constusage=parseFloat(execSync("df / | tail -1 | awk '{print $5}'").toString().replace('%', ''));
returnusage<85;
}
asyncautoRestart(service) {
// 实现自动重启...
}
asynccleanupDisk() {
// 实现磁盘清理...
}
}
newSelfHealing().run();
四、定制外观:让小龙虾的输出更好看
4.1 为什么外观很重要?
同样的内容,好看的排版让人更愿意看。
试想两个版本的巡检报告:
普通版:
cpu 35% memory 78% disk 62%美观版:
📊 服务器状态
CPU: ████████░░ 35%
内存: ████████████████░░░ 78%
磁盘: ████████████░░░░░░ 62%
哪个更想看?
4.2 使用 Emoji
Emoji 是让输出变好看的最简单方法:
| 场景 | 推荐 EMOJI |
|---|---|
| 成功 | ✅ 🎉 🚀 💪 |
| 失败 | ❌ 🚨 ⚠️ 🔴 |
| 进行中 | 🔄 ⏳ 🔍 🦞 |
| 信息 | 📢 📊 💡 🔗 |
4.3 使用进度条
functionrenderProgressBar(value, max=100, width=20) {
constpercentage=Math.min(value/max, 1);
constfilled=Math.round(percentage*width);
constempty=width-filled;
constbar='█'.repeat(filled) +'░'.repeat(empty);
constpercent=Math.round(percentage*100);
return`[${bar}] ${percent}%`;
}
console.log("CPU: "+renderProgressBar(35));
console.log("内存: "+renderProgressBar(78));
console.log("磁盘: "+renderProgressBar(62));
输出:
CPU: [███████░░░░░░░░░░░░] 35%
内存: [████████████████░░░░] 78%
磁盘: [███████████░░░░░░░░] 62%
4.4 使用表格
functionrenderTable(headers, rows) {
// 计算每列宽度
constwidths=headers.map((h, i) => {
constmaxRow=Math.max(...rows.map(r=>String(r[i]).length));
returnMath.max(h.length, maxRow);
});
// 表头
constheaderLine='| '+headers.map((h, i) =>h.padEnd(widths[i])).join(' | ') +' |';
constdivider='|'+widths.map(w=>'-'.repeat(w+2)).join('+|') +'|';
// 数据行
constdataLines=rows.map(row=> {
return'| '+row.map((cell, i) =>String(cell).padEnd(widths[i])).join(' | ') +' |';
});
return [headerLine, divider, ...dataLines].join('\n');
}
// 使用
constheaders= ["服务", "状态", "响应时间"];
constrows= [
["API", "✅ 正常", "45ms"],
["数据库", "✅ 正常", "12ms"],
["Redis", "❌ 异常", "-"],
];
console.log(renderTable(headers, rows));
输出:
| 服务 | 状态 | 响应时间 |
|--------|--------|----------|
| API | ✅ 正常 | 45ms |
| 数据库 | ✅ 正常 | 12ms |
| Redis | ❌ 异常 | - |
4.5 使用颜色(终端)
如果你的终端支持 ANSI 颜色码:
constcolors= {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
};
functioncolor(text, color) {
return`${colors[color]}${text}${colors.reset}`;
}
console.log(color("✅ 成功", "green"));
console.log(color("❌ 失败", "red"));
console.log(color("⚠️ 警告", "yellow"));
console.log(color("ℹ️ 信息", "blue"));
五、实战:打造你的专属运维助手
结合今天学到的所有内容,我们可以打造一个完整的运维助手:
// scripts/ops-assistant.js
classOpsAssistant {
constructor() {
this.name="小龙虾运维助手";
this.version="1.0.0";
}
asyncrun() {
console.log(`
🦞 ${this.name}v${this.version}
${'='.repeat(40)}
`);
// 1. 健康检查
awaitthis.healthCheck();
// 2. 自动化巡检
awaitthis.inspection();
// 3. 故障自愈
awaitthis.selfHealing();
console.log(`
${'='.repeat(40)}
🦞 运维巡检完成
`);
}
asynchealthCheck() {
console.log("📊 健康检查...\n");
// ... 实现见 2.3 节
}
asyncinspection() {
console.log("🔍 自动化巡检...\n");
// ... 实现见 2.3 节
}
asyncselfHealing() {
console.log("🔧 故障自愈检查...\n");
// ... 实现见 3.3 节
}
}
newOpsAssistant().run();
运行效果:
🦞 小龙虾运维助手 v1.0.0
========================================
📊 健康检查...
【服务器状态】
| 指标 | 状态 | 值 |
|------|------|-----|
| CPU | ✅ 正常 | 35.2% |
| 内存 | ⚠️ 偏高 | 78.5% |
| 磁盘 | ✅ 正常 | 62.1% |
🔍 自动化巡检...
【服务状态】
| 服务 | 状态 |
|------|------|
| Docker | ✅ 运行中 |
| Redis | ✅ 运行中 |
🔧 故障自愈检查...
✅ Redis 状态正常
✅ Docker 状态正常
✅ 无需自愈
========================================
🦞 运维巡检完成
六、常见问题
Q1: 自动巡检太频繁影响服务器性能?
把巡检间隔调大,或者使用轻量级的检查方式:
# 原来每分钟巡检
* * * * * /root/.openclaw/node/bin/node /root/.openclaw/workspace/skills/prometheus/scripts/health-check.js
# 改成每小时一次
0 * * * * /root/.openclaw/node/bin/node /root/.openclaw/workspace/skills/prometheus/scripts/health-check.js
Q2: 自愈操作失败了怎么办?
加入人工确认机制:
asyncfunctionautoFixWithConfirm(service) {
console.log(`⚠️ ${service}需要修复`);
console.log(`建议操作: systemctl restart ${service}`);
console.log(`请输入 "yes" 确认执行:`);
constanswer=awaitprompt(); // 等待用户输入
if (answer.toLowerCase() ==='yes') {
awaitautoRestart(service);
} else {
console.log("❌ 已取消,等待人工处理");
}
}
Q3: 如何让巡检报告发送到飞书?
参考 feishu-im 技能的说明,调用飞书机器人 API:
asyncfunctionsendToFeishu(message) {
awaitaxios.post('https://open.feishu.cn/open-apis/bot/v2/hook/xxx', {
msg_type: 'text',
content: { text: message }
});
}
今日小结
今天我们学会了:
✅ 安全加固:配置白名单/黑名单、使用 SSH 密钥、管理环境变量
✅ 自动化巡检:用 cron 定时任务 + 巡检脚本
✅ 故障自愈:自动重启、清理磁盘、自动扩容
✅ 定制外观:Emoji、进度条、表格、颜色
下期预告
小龙虾养殖日记(四)将会介绍:
🌐 开放 API:让小龙虾可以被其他系统调用
🔗 Webhook:小龙虾如何接收外部事件
🤖 多 Agent 协作:多只小龙虾一起工作
🏠 智能家居:用小龙虾控制家里的设备
敬请期待!
往期回顾:
🦞 小龙虾 OpenClaw 养殖日记(一)
🦞 小龙虾 OpenClaw 养殖日记(二)
🦞 小龙虾养殖日记,记录你与 AI 助手的日常
夜雨聆风