#!/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'));