logo hsb.horse
← Voltar para o índice do blog

Blog

Criar jobs Cron com PM2: como alternativa ao launchd

Como criar jobs periódicos com PM2 no macOS em vez de launchd. Um resumo do arquivo de configuração e de um exemplo de execução agendada com Bun.

Publicado:

Eu queria rodar tarefas periódicas no macOS, mas a configuração do launchd continua difícil de entender, então resolvi usar PM2 como caminho mais simples.

Configuração para rodar um job Cron com PM2

Terminal window
cd $PROJECT_ROOT
pm2 ecosystem

A configuração é gerenciada em ecosystem.config.cjs.

module.exports = {
apps: [
{
name: "cronJob",
script: "main.ts",
interpreter: "~/.bun/bin/bun",
// número de instâncias é 1
instances: 1,
// executar a cada 15 minutos
cron_restart: "*/15 * * * *",
exec_mode: "fork",
// reiniciar automaticamente quando arquivos mudarem: não
watch: false,
// reinício automático: não
autorestart: false,
},
],
};

Pontos

  • cron_restart: define o intervalo no formato cron
  • autorestart: false: como o processo roda como job agendado, o reinício automático fica desligado
  • interpreter: permite especificar qualquer runtime, incluindo Bun

Comando de inicialização:

Terminal window
pm2 start ecosystem.config.cjs
pm2 save

Exemplo de implementação do job

Um processo que obtém o IP periodicamente e grava em banco.

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();

Referências

Resumo

Com PM2, dá para gerenciar jobs agendados com uma configuração bem mais simples que launchd.

Definindo o job em ecosystem.config.cjs, também fica fácil aproveitar os recursos de gerenciamento de processo do PM2 para logs e reinícios quando necessário.