【OpenClaw 保姆级教程】第三篇:自定义技能开发 + 私有化部署(附完整可运行代码)

0 阅读15分钟

哈喽宝子们!上篇我们成功把 OpenClaw 接入 Telegram、Discord,还学会了文件管理、浏览器控制、联网搜索三大核心技能。今天直接进入进阶实战:从零开发一个属于你自己的技能,再把 OpenClaw 部署到服务器,24 小时在线不掉线,真正做到私有化、全自动运行!

没看完前两篇的同学先别跳步,确保本地能正常启动、渠道能正常收发消息,再来搞今天的内容~毕竟基础打牢了,进阶操作才能顺风顺水,避免踩不必要的坑。

一、本篇你能学到什么

今天的内容全程干货无废话,每一个知识点都是能直接落地的实战技能,学完你就能:

  1. 掌握 OpenClaw 自定义技能开发规范(通用模板,套啥功能都能用,后续开发任何技能都不用从零摸索);
  2. 实战开发「自动发邮件」核心技能(带完整可运行代码 + 邮箱配置避坑指南);
  3. 理解指令解析底层逻辑(让机器人精准听懂你发的中文指令,不再答非所问);
  4. 完成服务器私有化部署 + 后台常驻(用 PM2 守护进程,实现 24 小时不掉线);
  5. 规避开发和部署中的常见报错,做好安全配置(防止隐私泄露、机器人被滥用)。

二、自定义技能:通用开发模板(必背)

OpenClaw 的技能体系采用「模块化设计」,所有自定义技能都遵循统一的结构,记住这个模板,你能开发任何想要的功能 —— 小到自动查天气,大到自动生成报表,都能套进去。

2.1 技能开发核心原则

在写代码前,先明确三个核心原则,避免写出来的技能无法接入主程序:

  • 存放路径统一:所有技能文件必须放在项目根目录的 /skills 文件夹下,主程序会默认从这个目录加载技能;
  • 函数暴露规范:每个技能必须暴露可被主程序调用的执行函数(比如 sendEmail()),且函数返回值为「可读的文本结果」(方便机器人把结果返回给 Telegram/Discord);
  • 指令解析独立:每个技能建议自带指令解析函数(比如 parseEmailCommand()),把用户的自然语言指令转换成程序能识别的参数,降低主程序的耦合度。

2.2 通用模板代码(直接复制改)

javascript

运行

// /skills/xxxSkill.js
// 1. 引入依赖(根据技能需求添加,比如发邮件用nodemailer,爬取数据用axios)
const xxx = require('xxx');
require('dotenv').config(); // 加载环境变量,保护敏感信息

// 2. 核心执行函数(async/await处理异步操作,比如发邮件、调接口)
async function executeXxx(params) {
  try {
    // 核心业务逻辑:比如调用API、操作文件、发送消息
    const result = await xxx.doSomething(params);
    // 返回成功结果(格式统一,方便前端/机器人展示)
    return `✅ 操作成功:${JSON.stringify(result)}`;
  } catch (err) {
    // 返回失败结果(明确错误原因,方便排错)
    return `❌ 操作失败:${err.message}`;
  }
}

// 3. 指令解析函数(把用户的中文指令转成参数对象)
function parseXxxCommand(content) {
  // 用正则匹配用户指令中的关键信息,比如「收件人:xxx」「标题:xxx」
  const param1 = content.match(/参数1[::](.+?)(\s|\n|$)/)?.[1] || '';
  const param2 = content.match(/参数2[::](.+?)(\s|\n|$)/)?.[1] || '';
  // 返回参数对象,供执行函数使用
  return { param1, param2 };
}

// 4. 暴露函数,让主程序能调用
module.exports = { executeXxx, parseXxxCommand };

这个模板的优势在于:结构清晰、复用性强、易维护。哪怕你是编程新手,只要替换「依赖引入」「核心业务逻辑」「指令解析正则」这三部分,就能快速开发出新技能。

三、实战:开发「自动发邮件」技能

邮件发送是办公场景的高频刚需,比如自动发送日报、告警通知、客户回执等,我们以这个技能为例,一步步拆解开发过程,确保你能跟着做出来。

3.1 前期准备:邮箱 SMTP 配置

首先要开启邮箱的 SMTP 服务(以 QQ 邮箱为例,其他邮箱如 163、Gmail 操作类似):

  1. 登录 QQ 邮箱,点击右上角「设置」→「账户」;
  2. 找到「POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV 服务」;
  3. 开启「SMTP 服务」,按照提示完成短信验证,获取「SMTP 授权码」(注意:不是邮箱登录密码,这是第三方应用调用邮箱的专用密码);
  4. 记录下 SMTP 服务器信息:QQ 邮箱是 smtp.qq.com,端口 465(SSL 加密);163 邮箱是 smtp.163.com,端口 465

3.2 安装依赖

进入项目根目录,打开终端执行以下命令,安装邮件发送和环境变量管理的依赖:

bash

运行

# 安装nodemailer(邮件发送核心库)和dotenv(环境变量管理)
npm install nodemailer dotenv --save

安装完成后,查看项目根目录的 package.json 文件,确认 dependencies 里出现 nodemailerdotenv,说明依赖安装成功。

3.3 创建技能文件

/skills 文件夹下新建 emailSkill.js 文件,粘贴以下完整代码(带详细注释,看不懂的地方看注释):

javascript

运行

const nodemailer = require('nodemailer');
require('dotenv').config(); // 加载.env文件中的环境变量

/**
 * 邮件发送器配置(封装成函数,避免重复创建)
 * @returns {object} 配置好的transporter对象
 */
function createTransporter() {
  // 配置SMTP服务器信息,不同邮箱的配置不同,参考对应邮箱的官方文档
  return nodemailer.createTransport({
    host: process.env.EMAIL_SMTP_HOST, // SMTP服务器地址(从.env读取)
    port: process.env.EMAIL_SMTP_PORT, // 端口(465为SSL端口,587为TLS端口)
    secure: true, // true对应465端口,false对应587端口
    auth: {
      user: process.env.EMAIL_ACCOUNT, // 发件人邮箱账号(从.env读取)
      pass: process.env.EMAIL_AUTH_CODE // SMTP授权码(从.env读取)
    }
  });
}

/**
 * 执行邮件发送
 * @param {string} to 收件人邮箱(多个用逗号分隔,如"a@qq.com,b@163.com")
 * @param {string} subject 邮件标题
 * @param {string} text 邮件正文(纯文本)
 * @returns {string} 发送结果(成功/失败提示)
 */
async function sendEmail(to, subject, text) {
  // 校验必填参数,避免空值导致报错
  if (!to) return '❌ 收件人邮箱不能为空!';
  if (!subject) return '❌ 邮件标题不能为空!';
  if (!text) return '❌ 邮件正文不能为空!';

  try {
    const transporter = createTransporter();
    // 邮件发送配置
    const mailOptions = {
      from: `"OpenClaw智能助手" <${process.env.EMAIL_ACCOUNT}>`, // 发件人(显示名称+邮箱)
      to, // 收件人
      subject, // 标题
      text // 正文(纯文本)
      // 可选:如果需要发HTML格式的邮件,添加html字段
      // html: `<h1>${subject}</h1><p>${text}</p>`
    };

    // 发送邮件(异步操作,用await等待结果)
    let info = await transporter.sendMail(mailOptions); // 注意:原代码是sendEmail,这里是sendMail(nodemailer的正确方法)
    
    // 验证邮件是否发送成功
    if (info.messageId) {
      return `✅ 邮件发送成功!
📧 收件人:${to}
📝 标题:${subject}
🆔 邮件ID:${info.messageId}
💡 可登录发件人邮箱查看发送状态`;
    } else {
      return '❌ 邮件发送失败:未获取到邮件ID,请检查配置!';
    }
  } catch (err) {
    // 针对常见错误给出具体提示,方便排错
    let errorMsg = '';
    if (err.message.includes('Authentication failed')) {
      errorMsg = '邮箱账号或SMTP授权码错误,请检查.env文件配置!';
    } else if (err.message.includes('connect ECONNREFUSED')) {
      errorMsg = 'SMTP服务器连接失败,请检查服务器地址和端口!';
    } else if (err.message.includes('Invalid email')) {
      errorMsg = '收件人邮箱格式错误,请检查!';
    } else {
      errorMsg = err.message;
    }
    return `❌ 邮件发送失败:${errorMsg}`;
  }
}

/**
 * 解析用户的邮件发送指令(中文指令转参数)
 * @param {string} content 用户发送的指令文本(如「发送邮件 收件人:xxx@qq.com 标题:测试 内容:你好」)
 * @returns {object} 解析后的参数(to, subject, text)
 */
function parseEmailCommand(content) {
  // 正则匹配规则:匹配「收件人:xxx」「标题:xxx」「内容:xxx」格式的内容
  // 支持中文冒号「:」和英文冒号「:」,支持换行/空格分隔
  const to = content.match(/收件人[::](.+?)(\s|\n|$)/)?.[1]?.trim() || '';
  const subject = content.match(/标题[::](.+?)(\s|\n|$)/)?.[1]?.trim() || '';
  const text = content.match(/内容[::]([\s\S]+)/)?.[1]?.trim() || ''; // 内容可能包含换行,用[\s\S]匹配所有字符
  
  return { to, subject, text };
}

// 暴露函数,供主程序调用
module.exports = { sendEmail, parseEmailCommand };

3.4 配置环境变量(关键:保护敏感信息)

绝对不要把邮箱账号、授权码写死在代码里!一旦代码泄露,你的邮箱就可能被恶意使用。正确的做法是用 .env 文件管理敏感信息:

  1. 在项目根目录新建 .env 文件,写入以下内容(替换成你自己的信息):

env

# 邮箱配置
EMAIL_ACCOUNT=你的QQ邮箱@qq.com
EMAIL_AUTH_CODE=你的QQ邮箱SMTP授权码
EMAIL_SMTP_HOST=smtp.qq.com
EMAIL_SMTP_PORT=465

  1. 在项目根目录新建 .gitignore 文件(如果没有的话),添加 .env,防止把敏感信息提交到代码仓库:

gitignore

# 忽略环境变量文件
.env
# 忽略node_modules(依赖包,无需提交)
node_modules/
# 忽略日志文件
*.log

3.5 在主程序中挂载技能

找到 OpenClaw 的主程序入口(通常是 index.jsapp.js),在指令处理的位置添加以下代码,把邮件技能挂载进去:

javascript

运行

// 引入邮件技能
const { sendEmail, parseEmailCommand } = require('./skills/emailSkill');

// 假设这是你的消息处理函数(Telegram/Discord的消息监听)
async function handleMessage(msg) {
  // 匹配「发送邮件」指令
  if (msg.includes('发送邮件')) {
    // 解析用户指令中的参数
    const { to, subject, text } = parseEmailCommand(msg);
    // 执行发送邮件操作
    const result = await sendEmail(to, subject, text);
    // 把结果返回给用户(Telegram/Discord的消息发送方法)
    await sendReply(result);
    return;
  }

  // 其他指令处理(比如之前的文件管理、联网搜索)
  if (msg.includes('文件管理')) {
    // ... 原有逻辑
  }
}

3.6 测试邮件技能

启动本地的 OpenClaw 程序,在 Telegram/Discord 中给机器人发送以下指令(格式要对应解析函数的规则):

plaintext

发送邮件
收件人:你的测试邮箱@163.com
标题:OpenClaw自动发邮件测试
内容:这是通过OpenClaw自定义技能自动发送的邮件,24小时运行超方便!

如果一切配置正确,你会收到机器人返回的「✅ 邮件发送成功」提示,同时测试邮箱能收到这封邮件。如果失败,根据返回的错误提示排查:

  • 提示「Authentication failed」:检查 .env 中的邮箱账号和授权码是否正确;
  • 提示「connect ECONNREFUSED」:检查 SMTP 服务器地址和端口是否正确;
  • 提示「收件人邮箱不能为空」:检查指令格式是否正确,比如有没有写「收件人:」。

四、扩展:基于通用模板开发更多技能

掌握了上面的模板和邮件技能开发流程,你可以半小时内开发出其他实用技能,以下是几个高频场景的示例(附核心思路):

4.1 自动发微信消息技能

核心依赖wechaty(微信机器人库)开发思路

  1. 安装依赖:npm install wechaty wechaty-puppet-wechat --save
  2. 核心执行函数:初始化微信机器人,通过手机号 / 昵称匹配联系人,发送消息;
  3. 指令解析:匹配「发送微信」「联系人:xxx」「消息:xxx」;
  4. 注意:微信网页版接口可能有限制,可选用企业微信或第三方协议。

4.2 自动爬取天气技能

核心依赖axios(HTTP 请求)、cheerio(HTML 解析)开发思路

  1. 安装依赖:npm install axios cheerio --save
  2. 核心执行函数:调用免费天气 API(如高德天气 API),获取指定城市的天气数据;
  3. 指令解析:匹配「查天气」「城市:xxx」;
  4. 示例指令:「查天气 城市:北京」,机器人返回「北京今日天气:晴,温度 10-20℃」。

4.3 自动整理桌面文件技能

核心依赖fs(文件系统,Node.js 内置)、path(路径处理,Node.js 内置)开发思路

  1. 无需额外安装依赖,直接使用 Node.js 内置模块;
  2. 核心执行函数:读取桌面目录,按文件类型(图片、文档、视频)分类,移动到对应文件夹;
  3. 指令解析:匹配「整理桌面」即可,无需额外参数;
  4. 注意:处理文件时添加异常捕获,防止文件被占用导致报错。

4.4 自动备份数据库技能

核心依赖child_process(执行系统命令,Node.js 内置)开发思路

  1. 核心执行函数:调用mysqldump命令备份 MySQL 数据库,压缩后保存到指定目录;
  2. 指令解析:匹配「备份数据库」「数据库名:xxx」;
  3. 安全配置:数据库账号密码从.env读取,备份文件定期清理,防止占满服务器磁盘。

五、私有化部署:让 OpenClaw 24 小时运行

本地运行的机器人只能在电脑开机时使用,部署到服务器后,就能实现 24 小时在线,真正做到全自动运行。以下是详细的部署步骤(以阿里云轻量服务器为例,腾讯云 / 华为云操作一致)。

5.1 服务器选购与系统配置

  1. 选购建议:轻量应用服务器即可,配置无需太高(1 核 2G 内存、1M 带宽足够),系统选择「Ubuntu 20.04 LTS」或「Ubuntu 22.04 LTS」(兼容性最好);
  2. 安全组配置:登录服务器控制台,在安全组中开放必要端口(如 22 端口用于 SSH 连接,Telegram/Discord 的端口无需手动开放),禁止开放 3000、8080 等非必要端口,防止被攻击。

5.2 服务器环境安装

  1. 连接服务器:使用 FinalShell、Xshell 或 VS Code 的 Remote SSH 插件连接服务器(输入服务器 IP、端口 22、用户名 root、密码 / 密钥);
  2. 更新系统包:执行以下命令更新系统依赖,避免安装出错:

bash

运行

apt update && apt upgrade -y

  1. 安装 Node.js(18.x 版本,稳定版)

bash

运行

# 添加Node.js源
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
# 安装Node.js和npm
sudo apt install nodejs -y
# 验证安装(显示版本号则成功)
node -v # 应输出v18.x.x
npm -v # 应输出9.x.x

5.3 上传代码到服务器

  1. 创建项目目录:在服务器上新建目录,用于存放 OpenClaw 代码:

bash

运行

mkdir -p /usr/local/openclaw

  1. 上传代码

    • 方法 1(FinalShell):直接把本地项目文件夹拖到服务器的/usr/local/openclaw目录下;

    • 方法 2(Git):如果代码托管在 GitHub/Gitee,直接克隆:

      bash

      运行

      git clone 你的代码仓库地址 /usr/local/openclaw
      

  2. 安装项目依赖:进入项目目录,安装依赖:

bash

运行

cd /usr/local/openclaw
npm install

  1. 配置环境变量:在服务器的项目目录下新建.env文件,写入和本地一样的配置(邮箱、Telegram/Discord Token 等):

bash

运行

# 编辑.env文件
nano /usr/local/openclaw/.env
# 粘贴本地的.env内容,保存退出(按Ctrl+O,回车,Ctrl+X)

5.4 安装 PM2 守护进程(关键:后台常驻)

PM2 是 Node.js 的进程管理工具,能实现:后台运行程序、崩溃自动重启、服务器重启后自动启动、查看运行日志等功能,是部署 Node.js 应用的首选工具。

  1. 全局安装 PM2

bash

运行

npm install pm2 -g

  1. 启动 OpenClaw 并命名

bash

运行

cd /usr/local/openclaw
# 启动程序,命名为OpenClaw(方便管理)
pm2 start index.js --name "OpenClaw"

  1. 设置 PM2 开机自启

bash

运行

# 保存当前PM2的进程列表
pm2 save
# 设置开机自启(执行后按提示操作,通常需要输入服务器密码)
pm2 startup

  1. PM2 常用命令(必记)

bash

运行

# 查看运行状态
pm2 status
# 查看日志(实时监控程序运行情况)
pm2 logs OpenClaw
# 重启程序(修改代码后需要重启)
pm2 restart OpenClaw
# 停止程序
pm2 stop OpenClaw
# 删除程序
pm2 delete OpenClaw

执行完以上步骤,你的 OpenClaw 就会在服务器后台 24 小时运行 —— 哪怕关闭 SSH 连接、重启服务器,程序也会自动启动,真正实现「私有化、全自动」。

六、部署必看:安全配置与常见报错避坑

6.1 安全配置要点(重中之重)

  1. 敏感信息绝对不写死:所有 Token、账号、密码、授权码都通过.env文件管理,且.env必须加入.gitignore

  2. 服务器端口最小化开放:只开放 22(SSH)、80/443(如果有 Web 界面)端口,其他端口一律关闭;

  3. 限制机器人访问权限

    • Telegram:在代码中添加 chatId 白名单,只允许指定用户发送指令;
    • Discord:设置机器人仅能在指定服务器 / 频道工作;
  4. 定期备份代码和数据:服务器硬盘可能损坏,定期把项目文件和备份数据(如数据库备份)下载到本地;

  5. 避免使用 root 用户运行程序:创建普通用户,赋予项目目录的读写权限,用普通用户启动 PM2,降低安全风险。

6.2 常见报错及解决方案

  1. 报错:PM2 启动后程序立即退出

    • 原因:代码有语法错误、依赖未安装、环境变量配置错误;
    • 解决:执行pm2 logs OpenClaw查看具体错误日志,根据日志修复(比如缺少依赖就npm install xxx,语法错误就修正代码)。
  2. 报错:邮件发送失败「Authentication failed」

    • 原因:邮箱 SMTP 授权码错误、未开启 SMTP 服务、邮箱账号输入错误;
    • 解决:重新登录邮箱检查 SMTP 服务是否开启,重新获取授权码,确保.env中的配置和邮箱一致。
  3. 报错:Telegram 机器人收不到消息

    • 原因:Token 错误、服务器网络无法访问 Telegram、机器人未加入聊天群组;
    • 解决:检查 Token 是否正确,服务器 ping api.telegram.org测试网络,确保机器人已被添加到群组且有消息权限。
  4. 报错:PM2 startup 执行失败

    • 原因:服务器权限不足、PM2 版本过低;
    • 解决:更新 PM2 到最新版本(npm update pm2 -g),用 root 用户执行pm2 startup,按提示输入密码完成配置。
  5. 报错:服务器重启后 PM2 未自动启动

    • 原因:未执行pm2 savepm2 startup配置错误;
    • 解决:重新执行pm2 savepm2 startup,重启服务器后执行pm2 status验证。

七、下期预告

【OpenClaw 保姆级教程】第四篇:多技能联动 + 定时任务 + API 接口化,把 OpenClaw 变成全自动工作流!

有任何部署失败、指令不识别、邮件发不出的问题,直接评论区留言,我挨个帮你看~