서버에서 봇이 "작동하지 않는" 데는 두 가지가 있습니다. 뻔한 것: SSH를 닫는 순간 멈춥니다. 교활한 것: 이틀은 잘 돌다가 어떤 처리되지 않은 에러로 새벽 4시에 크래시하고, 누군가 왜 내려갔냐고 물을 때 몇 시간 뒤에 알게 됩니다. 둘 다 같은 해결책이고, 그것은 "재시작을 잊지 마세요"가 아닙니다 — 일을 systemd에 넘기는 것, 당신이 하지 않아도 되도록 것들을 계속 떠 있게 하는 것입니다.
로그아웃하면 왜 죽는가
SSH 세션에서 python bot.py로 띄웠다면, 프로세스는 그 세션의 자식입니다. 세션을 닫으면 프로세스도 함께 갑니다. nohup과 &는 이것을 덮지만, 크래시 시 재시작도 부팅 시 시작도 주지 않습니다 — 그래서 작은 문제를 풀고 큰 것을 남긴 셈입니다.
진짜 해결책: systemd 서비스
이것이 전부입니다. /etc/systemd/system/mybot.service를 만드세요:
[Unit]
Description=My bot
After=network-online.target
[Service]
WorkingDirectory=/home/youruser/mybot
ExecStart=/home/youruser/mybot/venv/bin/python bot.py
Restart=always
RestartSec=5
User=youruser
Environment=API_KEY=...
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now mybot
두 줄이 무거운 일을 합니다:
Restart=always— 봇이 크래시하면 systemd가 5초 안에 되돌립니다. 그 새벽 4시의 죽음이 아무도 알아채지 못하는 5초의 깜빡임이 됩니다.enable— 재부팅 후 스스로 다시 시작합니다. "아, 서버가 재부팅됐는데 전부 다시 띄우는 걸 잊었네"가 없어집니다.
그래도 말썽일 때 — 로그를 읽으세요
크래시 루프를 계속하는 봇은 더 세게 재시작한다고 고쳐지지 않습니다; 실제로 무언가 잘못됐습니다. systemd가 stdout/stderr를 잡으므로:
systemctl status mybot # 떠 있는지 내려갔는지, 마지막 종료 코드
journalctl -u mybot -n 100 # 최근 로그 + 죽은 원인 에러
journalctl -u mybot -f # 라이브로 따라가기
원인은 거의 항상 바로 거기 있습니다: 빠진 환경 변수, 처리되지 않은 예외, API 타임아웃, OOM 킬. 그것을 고치세요 — Restart=always는 안전망이지 진짜 버그의 치료가 아닙니다.
팁: 로그가 봇이 메모리 때문에 죽는다고 보여주면, 박스를 넘어 자란 것입니다 — 사이징 가이드를 확인하세요.
대신 tmux나 pm2가 의미 있을 때
systemd가 유일한 답은 아니고, 그저 최선의 기본값입니다:
- tmux — 빠른 테스트나 대화식 프로세스를 보는 데 완벽. 돌리고, 떼어내고, 나중에 다시 붙이기. 하지만 크래시에 재시작하지 않고 재부팅을 견디지 않으니 프로덕션용은 아닙니다.
- pm2 — 이미 Node 세계에 있고 프로세스 대시보드를 원하면 합리적. 함정: pm2 자체가 이제 살려 둬야 할 프로세스입니다(대개… systemd를 통해). 봇 하나에는 필요 없는 층입니다.
단일 상시 가동 봇이나 에이전트에는 systemd가 실제로 작동하는 가장 단순한 것 — 이미 서버에 있고, 추가 도구가 필요 없고, 재시작, 부팅 시 시작, 로깅을 기본으로 해냅니다.
솔직한 결론
가동 시간은 더 큰 서버나 더 많은 규율의 문제가 아닙니다 — 프로세스를 노트북에 묶지 않는 문제입니다. Restart=always와 enable을 붙인 systemd 유닛에 감싸고, 뭔가 어긋나면 journalctl을 확인하세요. 그것을 한 번 하면 당신이 지켜보든 자든 봇은 떠 있습니다. (새 박스? 먼저 잠그세요 — 24시간 봇은 24시간 표적이기도 합니다.)
돌릴 곳이 필요한가요? Nano 요금제(월 $3)가 봇을 24시간 내내 살립니다 — 나머지는 systemd가 합니다.
댓글
아직 댓글이 없습니다. 첫 번째가 되세요.