Homebrew unter macOS mit launchd Job aktualisieren

Der Paketmanager Homebrew ist ein sehr hilfreiches Werkzeug für Apples Betriebssystem macOS. Hiermit lassen sich diverse Programme direkt über die Kommandozeile installieren. Homebrew übernimmt hierbei den Download und die Installation der Programme. Über die Kommandozeile lassen sich dann auch bereits installierte Programme aktualisieren. Das setzt jedoch voraus, dass die Befehle regelmäßig manuell ausgeführt werden. Dafür lässt sich auch ein Alias Befehl einrichten, der wie folgt aussehen kann:

alias update='brew update; brew upgrade; brew cleanup;’

Wird dann der Befehl “update” eingegeben, werden die oben definierten Befehle der Reihe nach ausgeführt.

Um diese Aktion zu automatisieren, gibt es unter macOS das Framework “launchd”. Damit lassen sich Programme, Skripte und Daemons verwalten. Über eine sogenannte “Property List” wird definiert, wann eine bestimmte Aktion ausgeführt werden soll. Launchd kümmert sich dann eigenständig um die Ausführungen. Um seine mit Homebrew installierten Programme aktuell zu halten, kann eine entsprechende Property List unter „~/Library/LaunchAgents/com.michi.homebrewupdate.plist“ wie folgt definiert werden.

<?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>GroupName</key>
    <string>homebrewupdate</string>
    <key>Label</key>
    <string>com.michi.homebrewupdate</string>
    <key>LowPriorityIO</key>
    <true/>
    <key>Program</key>
    <string>/Users/michi/bin/homebrewupdate.sh</string>
    <key>RunAtLoad</key>
    <true/>
    <key>EnvironmentVariables</key>
    <dict>
      <key>PATH</key>
      <string>/bin:/usr/bin:/usr/local/bin</string>
    </dict>
    <key>StartCalendarInterval</key>
    <array>
      <dict>
        <key>Hour</key>
        <integer>0</integer>
      </dict>
      <dict>
        <key>Hour</key>
        <integer>8</integer>
      </dict>
      <dict>
        <key>Hour</key>
        <integer>16</integer>
      </dict>
    </array>
    <key>StandardErrorPath</key>
    <string>/tmp/michi.homebrewupdate.err</string>
    <key>StandardOutPath</key>
    <string>/tmp/michi.homebrewupdate.out</string>
  </dict>
</plist>

Hierbei sind folgende Parameter wichtig und können nach Belieben angepasst werden. Erforderlich ist dann jedoch, dass die Pfade, Dateinamen etc. entsprechend durchgängig angepasst werden.

<key>Program</key>
<string>/Users/michi/bin/homebrewupdate.sh</string>

Hier wird das auszuführende Skript angegeben, welches die benötigten Homebrew Befehle ausführt.

<key>StartCalendarInterval</key>

Über den Parameter “StartCalendarInterval” wird das Update alle 8 Stunden ausgeführt. Alternativ lässt sich auch ein Wert über den Parameter “StartInterval” definieren. Das hat jedoch den Nachteil, dass das Update nicht ausgeführt wird, sobald der Rechner aus dem Schlafmodus aufwacht. Es wird dann bis zur nächsten definierten Ausführung gewartet. StartCalendarInterval hingegen wird ausgeführt, sobald der Rechner wieder aktiv ist.

<key>StandardErrorPath</key>
<string>/tmp/michi.homebrewupdate.err</string>
<key>StandardOutPath</key>
<string>/tmp/michi.homebrewupdate.out</string>

Um im Fehlerfall einen Hinweis zu erhalten, werden die Ausgaben in ein Log geschrieben. Auch hier können die Pfade und Dateinamen beliebig gewählt werden.

Das auszuführende Skript kann unter “~/bin/homebrewupdate.sh“ abgespeichert werden.

#!/bin/bash

for task in 'update' 'upgrade' 'cleanup'
do
 echo "Executing brew $task"
 /usr/local/bin/brew $task
done

Das Skript muss dann noch ausführbar gemacht werden.

chmod +x ~/bin/homebrewupdate.sh

Sobald die Konfigurationen abgeschlossen sind, kann der launchd Job aktiviert werden.

launchctl load -w ~/Library/LaunchAgents/com.michi.homebrewupdate.plist

Unter “/tmp” werden dann direkt die beiden Ausgabedateien angelegt, die auf Fehler überprüft werden können. Alternativ lässt sich auch mit dem Befehl “launchctl list | grep homebrew” prüfen, ob der Job bereits läuft. Wenn alles funktioniert, werden ab sofort alle mit Homebrew installierten Programme automatisch im Hintergrund aktualisiert.