[Unit] Description=chan 小额实盘执行器(读信号总线,直接调 Bitget REST) # 搬运挂了执行器仍要活着——它得继续管在场仓位的 48 分钟超时平仓。 # 所以这里只写 Wants(弱依赖),不写 Requires Wants=network-online.target chan-live-ship.service After=network-online.target chan-live-ship.service # 频繁重启说明有真问题,别让它无限打交易所。5 分钟内起 5 次就停下等人。 # 注意这两项在 systemd 229+ 属于 [Unit],写在 [Service] 里会被忽略 StartLimitIntervalSec=300 StartLimitBurst=5 [Service] Type=simple User=chan Group=chan WorkingDirectory=/opt/chan # 密钥与参数在这个文件里,权限必须 600。用 EnvironmentFile 而不是 # Environment=,后者会出现在 `systemctl show` 的输出里 EnvironmentFile=/etc/chan-live/live.env ExecStart=/opt/chan/.venv/bin/python /opt/chan/live/live_exec.py Restart=always RestartSec=5 # 收到 stop 时给足时间:执行器要平掉在场仓位再退出 KillSignal=SIGINT TimeoutStopSec=90 StandardOutput=journal StandardError=journal SyslogIdentifier=chan-live-exec # ── 收紧权限 ────────────────────────────────────────────────────── # 生产进程只需要读 /opt/chan 和读写状态目录,别的一概不给。这几条很廉价, # 但真出了远程代码执行,爆炸半径小很多——而这个进程手里有交易权限的密钥 NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/var/lib/chan-live ProtectKernelTunables=true ProtectKernelModules=true ProtectControlGroups=true RestrictSUIDSGID=true LockPersonality=true MemoryMax=512M [Install] WantedBy=multi-user.target