macOS에서 주기 실행 작업을 하고 싶었는데, launchd 설정은 여전히 읽기 어렵고 더 편하게 가고 싶어서 PM2를 쓰기로 했다.
PM2로 Cron 작업을 돌리기 위한 설정
cd $PROJECT_ROOT
pm2 ecosystemecosystem.config.cjs 에서 설정을 관리한다.
module.exports = { apps: [ { name: "cronJob", script: "main.ts", interpreter: "~/.bun/bin/bun", // 인스턴스 수는 1 instances: 1, // 15분마다 실행 cron_restart: "*/15 * * * *", exec_mode: "fork", // 대상 파일이 바뀌었을 때 자동 재시작할지: 안 함 watch: false, // 자동 재시작할지: 안 함 autorestart: false, }, ],};포인트
- cron_restart: Cron 형식으로 실행 간격 지정
- autorestart: false: Cron 작업으로 실행하므로 자동 재시작은 끈다
- interpreter: Bun 같은 원하는 런타임을 지정 가능
실행 명령:
pm2 start ecosystem.config.cjs
pm2 save실행 작업 샘플 구현
IP 주소를 주기적으로 가져와 DB에 저장하는 처리.
import { Database } from 'bun:sqlite';
const DDL = `CREATE TABLE IF NOT EXISTS ip_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, ip TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP);`
async function fetchIpConfig() { const response = await fetch("https://ifconfig.io/ip").catch((err) => new Error(err)); if (response instanceof Error || !response.ok) { return null; }
const ip = await response.text();
return ip;}
async function main() { const ip = await fetchIpConfig(); if (ip == null) return;
using db = new Database('ip-monitor.sqlite', { create: true }); db.exec(DDL); using query = db.query("INSERT INTO ip_history (ip) VALUES ($ip);"); query.run({ $ip: ip });}
await main();참고 자료
- PM2 - Ecosystem File
- PM2でCronジョブを作成する方法 | NullNull
- How to make a task job with PM2? - Stack Overflow
정리
PM2를 쓰면 launchd 보다 훨씬 단순한 설정으로 Cron 작업을 관리할 수 있다.
ecosystem.config.cjs 에 작업을 정의해 두면 로그 확인과 필요 시 재시작 관리도 편해진다.
hsb.horse