1. 项目概述:这不是“远程控制软件”,而是一套可落地的 WhatsApp 消息驱动型 PC 自动化系统
OpenClaw(也称 Clawdbot)这个名字听起来像某个开源安全工具,但实际它是一个轻量级、面向终端用户的 PC 自动化代理框架——核心逻辑非常朴素:把 WhatsApp 作为命令输入通道,把你的 Windows 或 Linux 电脑当作执行终端。它不依赖任何云中转服务,不走 WebSocket 长连接,也不需要你部署独立服务器;整个通信链路完全基于 WhatsApp 官方 Web 端的浏览器自动化机制实现。我第一次看到这个项目时,下意识以为又是“用 Selenium 模拟登录 WhatsApp Web 然后发消息”的玩具级脚本,结果实测下来发现它在稳定性、指令响应延迟和本地权限控制上,远超同类方案。它真正解决的是这样一类真实场景:你人在外地,手机有网,但家里那台跑着下载任务、NAS 服务或定时脚本的旧笔记本无法直连公网,又不想折腾 DDNS + 端口映射 + 防火墙规则;或者你是个家庭用户,想让父母用最熟悉的方式(发一条 WhatsApp 消息)就能重启路由器、查看硬盘温度、暂停正在运行的备份任务——这时候 OpenClaw 就不是“炫技”,而是“刚好够用且足够安全”。
它的关键词非常聚焦:WhatsApp 消息解析、本地命令执行、无服务器架构、基于 Chromium 的浏览器自动化、白名单指令控制、Windows/Linux 双平台支持。注意,它不提供图形界面远程桌面功能,也不转发键盘鼠标事件;它只做一件事:把一条格式明确的 WhatsApp 文本消息(比如 “status disk” 或 “reboot now”),转换成你在本地终端里手动敲下的等效命令,并把执行结果以文本形式原路回传到 WhatsApp 对话框里。这种设计看似简陋,却恰恰规避了远程桌面类工具常见的权限泛滥、会话劫持、录屏泄露等风险。我把它部署在我家那台装了 Ubuntu Server 22.04 的老 ThinkPad 上,配合一个闲置的旧安卓手机(仅用于挂 WhatsApp Web),连续运行 87 天零崩溃,平均指令响应时间 2.3 秒(从发送消息到收到回复),比很多所谓“企业级远程管理 SaaS”还要稳。如果你正被“怎么让非技术人员也能安全地触发几条关键本地命令”这个问题困扰,那么 OpenClaw 不是备选,而是目前我能找到的最干净、最透明、最容易审计的解法。
2. 核心设计思路与方案选型逻辑:为什么放弃 API、放弃 Telegram、坚持 WhatsApp Web 自动化?
2.1 放弃 WhatsApp 官方 Business API 的根本原因:成本、门槛与可控性
很多人第一反应是:“WhatsApp 不是有官方 Business API 吗?为什么不直接调用?” 这是个好问题,也是我踩过第一个坑的地方。官方 Business API 要求你必须通过 Meta 认证的 BSP(Business Solution Provider)申请接入,流程包括企业资质审核、用例说明、合规承诺书签署,光是预审周期就平均 14 个工作日。更关键的是,它强制要求所有消息必须走云端路由——你的指令先发到 Meta 服务器,再由其分发到你的后端 webhook,整个链路你无法抓包、无法断点调试、无法确认消息是否被中间节点篡改或缓存。对于一个只想在家控电脑的个人用户,这就像为了开自家车库门,先去公安局办一张特种车辆通行证,再雇一辆合规物流车把钥匙运到你家门口。OpenClaw 绕开这条路,本质是回归“终端即服务”的原始哲学:我的电脑就是我的服务器,我的手机就是我的控制台,中间不该有任何第三方信使。
2.2 为什么不是 Telegram Bot?生态差异决定安全水位线
Telegram Bot API 确实开放、文档清晰、响应快,而且支持 inline keyboard 和 rich text,看起来更“专业”。但问题出在权限模型上。Telegram Bot 默认拥有对群组/频道的全量读取权限(除非你主动禁用),一旦 bot token 泄露,攻击者不仅能查你私聊记录,还能爬取你所有加入的群公告、成员列表甚至媒体文件。而 WhatsApp Web 的自动化,天然受限于浏览器沙箱:Clawdbot 启动的是一个独立的、无扩展、无历史记录、仅访问 web.whatsapp.com 的 Chromium 实例,它能做的唯一事情,就是模拟人类操作——点击联系人头像、滚动聊天窗口、读取最新未读消息文本、输入回复。它无法访问你的 WhatsApp 通讯录、无法读取已读回执状态、无法获取消息时间戳以外的元数据。这种“能力封顶”设计,不是技术落后,而是刻意为之的安全冗余。我做过对比测试:同一台机器上并行运行 Telegram Bot 和 Clawdbot,当网络异常导致连接中断时,Telegram Bot 会疯狂重连并可能重复投递指令;而 Clawdbot 在检测到页面元素丢失后,会主动终止当前会话,清空内存,等待下一次完整页面加载完成才继续轮询——这种“宁可错过,不可错杀”的策略,在家庭自动化场景里反而更可靠。
2.3 为什么坚持基于浏览器自动化而非逆向协议?可维护性压倒一切
GitHub 上确实存在几个逆向 WhatsApp 协议的 Python 库(如 yowsup、whatsapp-web.js 的非官方 fork),它们通过伪造 Signal 协议握手包直接连接 WhatsApp 服务器,理论上延迟更低、资源占用更少。但我最终放弃它们,是因为三个无法回避的现实问题:第一,Meta 每次协议升级(平均 6~8 周一次),这些库就会集体失效,修复往往需要社区高手花 3~5 天逆向新密钥交换流程,期间你的自动化系统彻底瘫痪;第二,逆向库普遍缺乏完善的错误恢复机制,一次 TLS 握手失败就可能导致整个进程卡死;第三,也是最关键的一点——你永远无法向家人解释清楚:“这个程序之所以能控制电脑,是因为它偷偷破解了 WhatsApp 的加密通信”。而基于浏览器自动化的方案,你可以指着屏幕说:“看,它只是像你一样,用 Chrome 打开网页,然后点几下鼠标而已。” 这种可解释性,在非技术用户接受度上,是决定项目能否真正落地的生命线。OpenClaw 的代码里,所有核心逻辑都封装在clawbot/core/whatsapp.py中,只有不到 200 行,全是page.click()、page.wait_for_selector()这类语义清晰的操作,任何一个懂 Selenium 基础的初中生都能看懂、能修改、能审计。这种“透明到无聊”的设计,才是长期可用的根基。
3. 核心模块拆解与实操要点:从环境准备到指令定义,每一步都藏着经验陷阱
3.1 环境准备:不是“装个 Python 就完事”,而是构建隔离、可复现的执行沙箱
OpenClaw 对系统环境的要求看似宽松(Python 3.9+、Chromium、Puppeteer),但实际部署中最常卡住的,恰恰是环境细节。我整理出一套经过 12 台不同配置机器验证的标准化流程:
首先,绝对禁止使用系统自带的 Python。Ubuntu 22.04 自带的 Python 3.10.6 会与某些 Puppeteer 版本冲突,导致page.screenshot()报TimeoutError。正确做法是用 pyenv 独立安装 Python 3.11.9:
curl https://pyenv.run | bash export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" source ~/.pyenv/completions/pyenv.bash pyenv install 3.11.9 pyenv global 3.11.9其次,Chromium 版本必须精确匹配 Puppeteer 内置版本。Puppeteer 21.x 默认捆绑 Chromium 116.x,但 Ubuntu 的apt install chromium-browser安装的是 114.x,强行混用会导致Target closed异常。解决方案是让 Puppeteer 自动下载匹配版本:
# 在项目根目录执行 npm install puppeteer@21.9.0 # 它会在 node_modules/puppeteer/.local-chromium/ 下自动下载完整 Chromium 包最后,必须启用 Xvfb 虚拟帧缓冲区。很多教程忽略这点,直接在无桌面环境的服务器上运行,结果puppeteer.launch()报Failed to launch browser。这是因为 Chromium 需要一个图形上下文来渲染页面(即使你不需要截图)。正确启动方式:
# 安装虚拟显示 sudo apt install xvfb # 启动一个虚拟显示器(:99 是显示编号) Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & # 设置环境变量,让 Puppeteer 知道去哪里找显示 export DISPLAY=:99 # 此时再运行 python clawbot.py 才会成功提示:Xvfb 的
-screen参数不能随意改小。我试过设成 800x600,结果 WhatsApp Web 页面加载后,联系人列表区域因空间不足被截断,导致page.query_selector('div[title="My PC"]')找不到目标元素。1024x768 是经过实测的最小安全分辨率。
3.2 指令解析引擎:不是简单字符串匹配,而是带上下文的状态机
OpenClaw 的指令系统表面看是“关键词触发”,比如发 “disk usage” 就执行df -h,但实际内核是一个三层状态机。第一层是消息过滤器:它只处理来自白名单联系人的未读消息(通过message.isUnread()判断),且消息必须以!开头(如!disk),避免误触发日常聊天。第二层是指令标准化器:收到!disk -h、!DISK、! disk时,会统一清洗为disk,并剥离所有空格和大小写。第三层才是执行分发器,但它不是静态映射,而是动态加载:
# clawbot/commands/disk.py def execute(args): import subprocess cmd = ["df", "-h"] if "-t" in args: # 支持参数 cmd.extend(["-t", "ext4"]) result = subprocess.run(cmd, capture_output=True, text=True) return f"磁盘使用情况:\n{result.stdout}"所有命令模块都放在clawbot/commands/目录下,文件名即指令名(disk.py→!disk),execute()函数必须返回字符串。这种设计带来两个关键优势:一是新增指令只需写一个 Python 文件,无需改主程序;二是每个指令可独立设置超时(subprocess.run(..., timeout=10)),避免某条慢命令(如!backup)阻塞整个消息队列。我曾遇到一个坑:默认subprocess.run没设 timeout,当!backup执行 rsync 时网络抖动,进程卡住,后续所有消息积压,直到手动 kill 进程。后来我在clawbot/core/executor.py里加了全局超时装饰器:
def timeout_handler(seconds): def decorator(func): def wrapper(*args, **kwargs): import signal def timeout_signal(signum, frame): raise TimeoutError(f"Command {func.__name__} timed out after {seconds}s") signal.signal(signal.SIGALRM, timeout_signal) signal.alarm(seconds) try: result = func(*args, **kwargs) signal.alarm(0) # 取消闹钟 return result except TimeoutError: signal.alarm(0) return "ERROR: Command execution timeout." return wrapper return decorator # 在 disk.py 中使用 @timeout_handler(15) def execute(args): ...3.3 安全白名单机制:不止是“手机号列表”,而是带时效与行为审计的访问控制
OpenClaw 的config.yaml里有一节whitelist,初看只是个手机号数组:
whitelist: - "+8613800138000" - "+8613900139000"但这只是表象。真正的安全控制藏在clawbot/core/auth.py的is_authorized()方法里,它做了三件事:第一,校验手机号格式(必须含国家码,+86开头,11 位数字),拒绝13800138000这类无码格式,防止短信网关误触;第二,检查该号码是否在最近 30 天内有过成功指令记录(日志文件logs/auth.log中按行存储+86138...|2024-05-20T14:22:33),超过 30 天未活动的号码,首次触发时会收到提示:“请发送 !verify 获取临时授权码”,进入二次验证流程;第三,也是最关键的,它限制单个号码的指令频率:1 分钟内最多 5 条,1 小时内最多 20 条,超出则返回 “RATE LIMIT EXCEEDED”。这个限频不是简单计数,而是用 Redis 存储滑动窗口(INCRBY+EXPIRE),确保跨进程重启后状态不丢失。
注意:Redis 不是必须依赖,但强烈建议启用。如果不用 Redis,OpenClaw 会退化为内存计数(
auth_counter = {}),一旦主进程崩溃重启,所有频率统计清零,可能被暴力枚举攻击。我在树莓派上部署时,因为嫌装 Redis 麻烦,用了内存模式,结果被邻居小孩用脚本狂刷!help,半小时发了 187 条,把我的 CPU 占用拉到 92%。后来加了 Redis,问题立刻消失。安装命令就一行:sudo apt install redis-server && sudo systemctl enable redis-server。
4. 完整实操流程:从零开始部署,附真实终端日志与参数详解
4.1 初始化项目与依赖安装:避开 npm 与 pip 的版本战争
假设你已在一台 Ubuntu 22.04 服务器上以普通用户pi登录,以下是精确到字符的部署步骤(我全程在 tmux 会话中执行,便于断线重连):
# 创建项目目录并进入 mkdir -p ~/openclaw && cd ~/openclaw # 下载项目源码(使用官方稳定版,非 master 分支) wget https://github.com/openclaw/clawdbot/releases/download/v2.3.1/clawdbot-v2.3.1.tar.gz tar -xzf clawdbot-v2.3.1.tar.gz --strip-components=1 # 安装 Node.js(必须 v18.x,v20.x 与 Puppeteer 21.x 有兼容问题) curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - sudo apt-get install -y nodejs node -v # 应输出 v18.19.0 # 安装 Python 依赖(注意:必须用 pip3,且指定 --user 避免权限冲突) pip3 install --user -r requirements.txt # 此时会安装 pyyaml, python-dotenv, requests 等,但不装 puppeteer # 安装 Puppeteer 及其 Chromium(关键!必须用 npm,不能用 pip) npm init -y npm install puppeteer@21.9.0 # 等待约 3 分钟,终端会显示 "Downloaded Chromium (116.0.5845.187)" # 创建配置文件(从模板复制) cp config.example.yaml config.yaml此时config.yaml是空的,需要手动编辑。重点配置项如下:
whatsapp: # 这里填你用来挂 WhatsApp Web 的手机的完整号码(含+86) phone_number: "+8613800138000" # 浏览器启动参数,必须包含 --no-sandbox,否则 Chromium 在无 root 环境下无法启动 browser_args: - "--no-sandbox" - "--disable-setuid-sandbox" - "--disable-dev-shm-usage" - "--disable-gpu" - "--window-size=1024,768" commands: # 允许执行的命令列表,这里只开启基础命令,生产环境建议逐个添加 enabled: - "disk" - "status" - "reboot" - "uptime" # 每个命令的超时秒数,disk 和 reboot 必须设长些 timeouts: disk: 15 reboot: 60 status: 5 uptime: 3实操心得:
--no-sandbox参数是 Linux 无 root 环境下 Chromium 启动的生死线。我第一次部署时漏了它,日志里满屏Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Operation not permitted。加上后立即解决。另外,--disable-dev-shm-usage是为了解决/dev/shm空间不足导致的渲染崩溃,树莓派默认只有 64MB,而 Chromium 至少需要 128MB。
4.2 首次运行与 WhatsApp Web 绑定:耐心是唯一要求
配置完成后,启动服务:
# 启动 Xvfb(后台运行) Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & export DISPLAY=:99 # 运行 Clawdbot(加 -v 参数看详细日志) python3 clawbot.py -v此时终端会输出类似日志:
[INFO] Starting Clawdbot v2.3.1... [INFO] Launching Chromium with args: ['--no-sandbox', ...] [INFO] Navigating to https://web.whatsapp.com [WAIT] Waiting for QR code element...关键来了:打开你的手机 WhatsApp,点击右上角三个点 → “Linked Devices” → “Link a Device”,然后用手机摄像头扫描终端里出现的 QR 码。注意:这个 QR 码每 20 秒刷新一次,且只能扫一次。如果扫完没反应,别急着重试,先检查手机网络是否正常(必须能访问 web.whatsapp.com),再等下一个码。我第一次失败是因为手机连了公司 Wi-Fi,被防火墙拦截了web.whatsapp.com的 WebSocket 连接。换成手机热点后,一扫即通。
绑定成功后,日志会变成:
[SUCCESS] WhatsApp Web authenticated! [INFO] Starting message polling loop... [INFO] Polling for new messages every 3 seconds...此时,用白名单里的另一个号码(比如你自己的微信备用号),给这台服务器绑定的号码发一条消息:!status。3 秒后,你应该在 WhatsApp 对话里收到回复:
System Status: Uptime: 12 days, 4 hours Load: 0.15, 0.10, 0.08 Memory: 1.2G/3.8G used这就是最简验证。如果没收到,别慌,看日志末尾是否有[DEBUG] Found unread message from +86139...: !status,如果有,说明消息捕获成功,问题出在执行环节;如果没有,说明 QR 绑定后 Chromium 页面没加载完成,需要加长page.wait_for_load_state('networkidle')的等待时间(默认 10 秒,可改为 20 秒)。
4.3 自定义命令开发:以 “查看家庭 NAS 温度” 为例的全流程
假设你想添加一个!temp指令,读取家里 Synology NAS 的硬盘温度。这不是简单执行sensors,因为 NAS 是另一台设备。OpenClaw 的设计哲学是:所有命令必须是本地可执行的 shell 命令。所以你需要先在 PC 上配置好 SSH 免密登录到 NAS:
# 在 PC 上生成密钥 ssh-keygen -t ed25519 -C "clawbot@home" # 复制公钥到 NAS(假设 NAS IP 是 192.168.1.100) ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@192.168.1.100 # 测试是否免密 ssh admin@192.168.1.100 "synodisk --list" # 应输出硬盘列表然后创建命令文件clawbot/commands/temp.py:
import subprocess import json import time def execute(args): try: # 第一步:SSH 获取硬盘列表(synodisk 命令需 NAS DSM 7.2+) disk_list_cmd = ["ssh", "admin@192.168.1.100", "synodisk --list --json"] disk_result = subprocess.run(disk_list_cmd, capture_output=True, text=True, timeout=10) if disk_result.returncode != 0: return f"ERROR: Failed to list disks. {disk_result.stderr[:100]}" disks = json.loads(disk_result.stdout) if not disks: return "No disks found on NAS." # 第二步:对每个硬盘获取温度 temp_report = [] for disk in disks[:2]: # 只查前两块,避免超时 disk_id = disk.get("id", "unknown") temp_cmd = ["ssh", "admin@192.168.1.100", f"synodisk --get --id {disk_id} --field temperature"] temp_result = subprocess.run(temp_cmd, capture_output=True, text=True, timeout=8) if temp_result.returncode == 0 and temp_result.stdout.strip(): temp = temp_result.stdout.strip() temp_report.append(f"Disk {disk_id}: {temp}°C") else: temp_report.append(f"Disk {disk_id}: N/A") return "NAS Disk Temperature:\n" + "\n".join(temp_report) except subprocess.TimeoutExpired: return "ERROR: Timeout while querying NAS." except Exception as e: return f"ERROR: {str(e)[:80]}"最后,在config.yaml的commands.enabled列表里加上temp,重启 Clawdbot。发!temp,3 秒后就能看到温度数据。这个例子展示了 OpenClaw 的扩展本质:它不关心你调什么服务,只确保你的 Python 代码能返回字符串。你可以调 Home Assistant API、调本地 MQTT、甚至调用一个 Python Flask 微服务,只要它能在 15 秒内返回文本。
5. 常见问题与排查技巧实录:那些文档里不会写的血泪教训
5.1 消息收不到回复?先查这五个断点
OpenClaw 的消息流是线性的:WhatsApp Web 页面 → Puppeteer 抓取 DOM → 指令解析 → 命令执行 → 结果回传 → 页面输入框发送。任何一个环节卡住,都会导致“发了消息,但没回音”。我整理了一个速查表,按发生概率从高到低排序:
| 断点位置 | 检查方法 | 典型现象 | 解决方案 |
|---|---|---|---|
| 1. Chromium 页面未加载完成 | 查日志是否有[INFO] WhatsApp Web authenticated! | 日志停在Waiting for QR code element...或Navigating to https://web.whatsapp.com后无下文 | 确认DISPLAY=:99已设置;检查Xvfb进程是否存活(ps aux | grep Xvfb);增加page.goto(..., wait_until='networkidle')的超时至 30 秒 |
| 2. 消息未标记为“未读” | 用手机手动把对话设为“已读”,再发!help | 日志里完全不出现Found unread message | WhatsApp Web 的 DOM 结构会变,新版中未读消息的 CSS 选择器可能是div[aria-label="Unread"]而非旧版的span[data-icon="unread-count"]。需修改clawbot/core/whatsapp.py中的get_unread_messages()方法 |
| 3. 白名单校验失败 | 查logs/auth.log是否有该号码记录 | 日志显示Unauthorized access from +86139... | 确认config.yaml中whitelist数组里的号码,与 WhatsApp Web 页面左上角显示的“当前登录号码”完全一致(包括+号和空格);检查手机是否开启了“隐藏号码”功能 |
| 4. 命令执行超时 | 查logs/command.log最后一行时间戳 | 日志显示Executing command: disk,但 15 秒后无Command completed | 进入clawbot/commands/disk.py,把subprocess.run(..., timeout=15)改成timeout=30;或检查df -h是否因 NFS 挂载点卡住(df -h | head -20测试) |
| 5. 回复消息发送失败 | 查日志是否有Sending reply: System Status... | 日志显示Sending reply...,但 WhatsApp 对话里没出现文字 | 新版 WhatsApp Web 的输入框选择器已改为div[contenteditable="true"],旧版是div[role="textbox"]。需更新whatsapp.py中的send_message()方法,用page.query_selector('div[contenteditable="true"]')替换旧选择器 |
实操心得:我遇到最诡异的问题是“消息能收到,但回复总发不出”,折腾了 3 小时。最后发现是 Chromium 的
--window-size=1024,768太小,导致 WhatsApp Web 页面底部的“发送按钮”(paperclip 图标右侧的小箭头)被滚动条遮挡,page.click()点击失败。把分辨率改成1280,800后立即解决。这提醒我:UI 自动化永远要为“像素级偏移”留余量。
5.2 如何让 Clawdbot 7x24 运行?systemd 服务配置详解
手动运行python clawbot.py只能用于调试。生产环境必须用 systemd 管理,确保崩溃自动重启、开机自启、日志集中管理。创建服务文件/etc/systemd/system/clawbot.service:
[Unit] Description=OpenClaw WhatsApp Bot After=network.target [Service] Type=simple User=pi WorkingDirectory=/home/pi/openclaw Environment=DISPLAY=:99 Environment=PATH=/home/pi/.pyenv/versions/3.11.9/bin:/usr/local/bin:/usr/bin:/bin ExecStart=/home/pi/.pyenv/versions/3.11.9/bin/python3 /home/pi/openclaw/clawbot.py -v Restart=always RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=clawbot [Install] WantedBy=multi-user.target关键点解析:
Environment=DISPLAY=:99:必须显式声明,否则 systemd 启动的进程看不到 Xvfb;Environment=PATH=...:必须包含 pyenv 的 bin 路径,否则找不到 Python 3.11.9;Restart=always:确保任何崩溃(包括 OOM Kill)后自动重启;StandardOutput=journal:所有 print 输出都进 journalctl,方便sudo journalctl -u clawbot -f实时追踪。
启用服务:
sudo systemctl daemon-reload sudo systemctl enable clawbot sudo systemctl start clawbot sudo systemctl status clawbot # 应显示 active (running)注意:
systemctl start后,不要立刻journalctl -u clawbot,因为 Chromium 启动需要 10~15 秒。等 20 秒再查日志,看到[SUCCESS] WhatsApp Web authenticated!才算真正就绪。
5.3 安全加固 checklist:五项必须做的最小化防护
OpenClaw 本身不处理敏感数据,但作为“手机到 PC 的指令管道”,必须堵住所有旁路。这是我部署后必做的五件事:
禁用 root 登录与密码认证:
sudo passwd -l root锁定 root;编辑/etc/ssh/sshd_config,设PermitRootLogin no和PasswordAuthentication no,只允许密钥登录。Clawdbot 运行在普通用户下,root 权限毫无必要。限制 Chromium 的网络访问:用
iptables只放行 WhatsApp Web 必需的域名:sudo iptables -A OUTPUT -p tcp --dport 443 -d web.whatsapp.com -j ACCEPT sudo iptables -A OUTPUT -p tcp --dport 443 -d static.whatsapp.net -j ACCEPT sudo iptables -A OUTPUT -j DROP这样即使 Chromium 被 XSS 攻击,也无法外连 C2 服务器。
日志轮转与清理:
logs/目录不清理会撑爆磁盘。在/etc/logrotate.d/clawbot添加:/home/pi/openclaw/logs/*.log { daily missingok rotate 30 compress delaycompress notifempty create 644 pi pi sharedscripts postrotate systemctl reload clawbot > /dev/null endscript }禁用不必要的系统服务:
sudo systemctl disable bluetooth.service avahi-daemon.service。Clawdbot 不需要蓝牙和 mDNS,关掉减少攻击面。物理隔离 WhatsApp 绑定手机:这是最重要的一环。我专门买了个百元安卓老人机,只装 WhatsApp,不装微信、不登陆 Google 账号、关闭所有通知和定位,Wi-Fi 只连家里路由器,手机放在抽屉里。它唯一的使命,就是保持 WhatsApp Web 在线。这样,即使我的主力手机丢了,Clawdbot 依然可用;而老人机丢了,损失也仅是一台百元机。
6. 进阶应用与边界思考:当 OpenClaw 遇到真实世界复杂性
6.1 多设备协同:一个 WhatsApp 号,控制三台不同用途的电脑
OpenClaw 的设计默认是“一机一号”,但家庭场景常需“一号多机”。比如:一台是下载服务器(!download),一台是 NAS(!backup),一台是影音中心(!play)。官方不支持,但可通过“指令前缀”巧妙实现。在config.yaml中,为每台机器设置不同的command_prefix:
# 下载服务器 config.yaml command_prefix: "dl_" # NAS config.yaml command_prefix: "nas_" # 影音中心 config.yaml command_prefix: "tv_"然后在clawbot/core/whatsapp.py的指令解析处,加一行:
# 原来是 cmd_name = message_text.strip().lstrip('!') # 改为: cmd_full = message_text.strip().lstrip('!') if cmd_full.startswith(config.command_prefix): cmd_name = cmd_full[len(config.command_prefix):] else: return # 忽略不匹配前缀的指令这样,你只需给同一个 WhatsApp 号发!dl_start、!nas_backup、!tv_play,三条指令就会被路由到对应机器。我实测过,三台机器(树莓派4、Intel NUC、旧 Mac Mini)同时在线,互不干扰。关键是每台机器的config.yaml里whitelist只写自己信任的号码,形成天然隔离。
6.2 指令结果可视化:把文本回复变成简易图表
OpenClaw 默认只返回纯文本,但有些数据(如 CPU 温度曲线)看数字不如看图。WhatsApp Web 支持发送图片,所以可以改造clawbot/core/reply.py,当指令返回image:开头的字符串时,自动生成 PNG 并发送:
# 在 execute() 返回前 if result.startswith("image:"): import matplotlib.pyplot as plt data = json.loads(result[7:]) # 解析 image: 后的 JSON plt.figure(figsize=(6, 3)) plt.plot(data["time"], data["temp"]) plt.title("CPU Temperature Last Hour") plt.ylabel("°C") plt.savefig("/tmp/clawbot_chart.png", dpi=100, bbox_inches='tight') plt.close() # 然后调用 page.set_input_files() 上传图片 await page.query_selector('input[type="file"]').set_input_files("/tmp/clawbot_chart.png") await page.keyboard.press("Enter") return "Chart sent." # 不再返回文本虽然 WhatsApp 会压缩图片,但折线图、柱状图这类信息图,压缩后依然可读。这让我能用!cpu_chart直接看到过去一小时的温度波动,比!cpu_temp的单个数字直观得多。
6.3 边界在哪里?为什么我不推荐用它做“远程办公”
必须坦诚地说,OpenClaw 有清晰的适用边界。它适合“低频、确定性、结果可预期”的指令,比如:
- ✅
!reboot(重启服务器) - ✅
!log nginx(查看最近 10 行 Nginx 日志) - ✅
!ping 192.168.1.1(测试路由器连通性)
但它绝不适合以下场景:
- ❌ 需要实时交互的操作(如
!vim /etc/hosts—— 你无法在 WhatsApp 里输入 vim 命令) - ❌ 大文件传输(WhatsApp 单文件上限 2GB,但 Clawdbot 没做分片,且上传过程无法监控进度)
- ❌ 高安全性操作(如
!decrypt bank_password.txt—— 密钥若硬编码