Files
clawd/bin/clawd.js

85 lines
2.6 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
'use strict';
// 先于其它模块:摘掉 NOTIFY_SOCKET避免任意子进程误发 systemd notify
require('../lib/systemd-env');
const path = require('path');
const { exec } = require('child_process');
const { ClawClient } = require('../lib/client');
const config = require('../lib/config');
const log = require('../lib/logger');
const { pollSms } = require('../drivers/sim/sms-reader');
// 启动时确保 clawd.service ReadWritePaths 包含 /etc/hosts /etc/hostname幂等修复
const fs = require('fs');
const SERVICE_FILE = '/etc/systemd/system/clawd.service';
try {
const svc = fs.readFileSync(SERVICE_FILE, 'utf8');
if (svc.includes('ReadWritePaths=') && !svc.includes('/etc/hosts')) {
const fixed = svc.replace(/ReadWritePaths=([^\n]*)/, (_, rest) =>
`ReadWritePaths=${rest.trimEnd()} /etc/hosts /etc/hostname`);
fs.writeFileSync(SERVICE_FILE, fixed, 'utf8');
exec('systemctl daemon-reload', () => {});
log.info('clawd', 'clawd.service ReadWritePaths fixed');
}
} catch (_) {}
// 每次启动绑定 Quectel 串口驱动(失败不影响主流程)
const bindScript = path.join(__dirname, '..', 'tools', 'bind-quectel-serial.sh');
exec(`bash "${bindScript}"`, (err, stdout, stderr) => {
if (err) log.warn('clawd', `bind-quectel-serial: ${stderr || err.message}`);
else log.info('clawd', `bind-quectel-serial: ok`);
});
// 同步 Samba 共享密码idempotent失败不影响主流程
const cfg = config.load();
if (cfg.share_key) {
const shareKey = cfg.share_key.replace(/'/g, "'\\''");
exec(`printf '%s\\n%s\\n' '${shareKey}' '${shareKey}' | smbpasswd -a sts -s 2>/dev/null`, (err) => {
if (err) log.warn('clawd', `smbpasswd sync failed (samba not installed?): ${err.message}`);
else log.info('clawd', 'smbpasswd synced for user sts');
});
}
let smsTimer = null;
let smsPolling = false;
async function pollSmsSafe() {
if (smsPolling) return;
smsPolling = true;
try {
const text = await pollSms();
process.stdout.write(text);
} catch (err) {
log.warn('clawd', `sms-reader poll failed: ${err.message}`);
} finally {
smsPolling = false;
}
}
const client = new ClawClient();
client.start();
pollSmsSafe();
smsTimer = setInterval(pollSmsSafe, 15_000);
let stopping = false;
function shutdown(signal) {
if (stopping) return;
stopping = true;
log.info('clawd', `收到 ${signal},正在停止...`);
if (smsTimer) {
clearInterval(smsTimer);
smsTimer = null;
}
client.stop();
setTimeout(() => process.exit(0), 500);
}
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));