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でジョブを定義し、PM2のプロセス管理機能を活用することで、ログ確認や再起動も簡単に行える。
hsb.horse