logo hsb.horse
← Zur Blog-Übersicht

Blog

Führen Sie mit macOS Launchd ein regelmäßiges Ausführungsskript aus

So erstellen Sie ein Skript, das wie Cron unter macOS Launchd jede Minute ausgeführt wird. Setup-Anweisungen, die Probleme mit Umgebungsvariablen vermeiden und die Protokollverwaltung umfassen.

Veröffentlicht: Aktualisiert:

Verwenden Sie macOS Launchd, um ein Skript zu erstellen, das wie Cron regelmäßig ausgeführt wird. Da das Einrichten von Umgebungsvariablen mühsam ist, verwenden wir eine Methode, die die Einstellungen auf der Plist-Seite minimiert.

Die Konfiguration ist wie folgt.

plist → wrapper shell → main shell

Wrapper-Skript

Legen Sie Umgebungsvariablen fest, führen Sie das eigentliche Skript aus und leiten Sie zum Protokoll um.

#!/bin/bash
# XDG環境変数の設定
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
# ログディレクトリの作成
LOG_DIR="$XDG_STATE_HOME/cron-like"
mkdir -p "$LOG_DIR"
# 実際のスクリプトを実行してログにリダイレクト
exec "$HOME/.local/bin/cron-like/every-minute.sh" \
>> "$LOG_DIR/stdout.log" 2>> "$LOG_DIR/stderr.log"

Plist-Einstellungen

Stellen Sie die Ausführung jede Minute ein.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>localhost.cron.every-minute</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/username/.local/bin/cron-like/launchd.sh</string>
</array>
<key>StartInterval</key>
<integer>60</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Setup-Skript

Automatisieren Sie die komplette Einrichtung.

#!/bin/bash
set -e
# ディレクトリの作成
mkdir -p "$HOME/.local/bin/cron-like"
mkdir -p "$HOME/.local/state/cron-like"
mkdir -p "$HOME/Library/LaunchAgents"
# ラッパースクリプトの作成
cat > "$HOME/.local/bin/cron-like/launchd.sh" <<'EOF'
#!/bin/bash
# XDG環境変数の設定
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
# ログディレクトリの作成
LOG_DIR="$XDG_STATE_HOME/cron-like"
mkdir -p "$LOG_DIR"
# 実際のスクリプトを実行してログにリダイレクト
exec "$HOME/.local/bin/cron-like/every-minute.sh" \
>> "$LOG_DIR/stdout.log" 2>> "$LOG_DIR/stderr.log"
EOF
# 実行スクリプトの作成
cat > "$HOME/.local/bin/cron-like/every-minute.sh" <<'EOF'
#!/bin/bash
# 実際の処理
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Running every-minute task"
# ここに実際の処理を記述
EOF
# 実行権限の付与
chmod +x "$HOME/.local/bin/cron-like/launchd.sh"
chmod +x "$HOME/.local/bin/cron-like/every-minute.sh"
# plistの作成
LABEL="localhost.cron.every-minute"
PLIST_PATH="$HOME/Library/LaunchAgents/${LABEL}.plist"
cat > "$PLIST_PATH" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${LABEL}</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>$HOME/.local/bin/cron-like/launchd.sh</string>
</array>
<key>StartInterval</key>
<integer>60</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
# 構文チェック
plutil -lint "$PLIST_PATH"
# 既にロードされている場合はアンロード
launchctl list | grep -q "$LABEL" && launchctl unload "$PLIST_PATH" 2>/dev/null || true
# ロード
launchctl load "$PLIST_PATH"
echo "✓ Setup complete!"
echo " Scripts: $HOME/.local/bin/cron-like/"
echo " Logs: $HOME/.local/state/cron-like/"
echo " plist: $PLIST_PATH"
echo ""
echo "Commands:"
echo " tail -f $HOME/.local/state/cron-like/stdout.log"
echo " launchctl start $LABEL"
echo " launchctl unload $PLIST_PATH"