programmazione,

Automatizzare il Mac dal Terminale - Una soluzione targata Apple

Sabino Maggi Sabino Maggi Segui 11-Dec-2014 · 8 minuti di lettura
Condividi

Dopo i programmi di derivazione Unix, at e cron, è la volta di parlare di launchd, una soluzione sviluppata dalla Apple per OS X.

Launchd

Launchd è il programma che, a partire dalla versione 10.4 (Tiger) di OS X, esegue tutti i processi di avvio del sistema operativo e che, come se non bastasse, può anche svolgere i compiti eseguiti da cron.

Launchd è stato sviluppato dalla Apple e, dopo qualche incomprensione, è stato rilasciato sotto la licenza open source Apache, con l’intento di promuoverne l’adozione anche sotto Linux e BSD. Finora però l’accoglienza al di fuori di OS X è stata tiepida, se non peggio, e quindi al momento launchd rimane confinato al solo Mac.

La cosa non mi stupisce.

Al di là degli aspetti tecnici relativi al porting su altre piattaforme e focalizzando l’attenzione solo sull’utilizzo di launchd al posto di cron, sono perfettamente d’accordo con quanto è stato scritto tempo fa su Low End Mac, con il titolo significativo Apple’s launchd Is Anti-Unix (Launchd di Apple è anti-Unix).

One of the great things about Unix-like systems is that most of your skills, programs, dot files, and highly polished shell scripts are portable. I brought them with me to OS X after dragging them through a dozen or so Linux distributions…
Consequently, I was distressed when launchd emerged from the dark side of One Infinite Loop…
Merging periodically run jobs into the main system process doesn’t make sense. Replacing a simple /etc/crontab text file with multiple, awkwardly named XML plist files scattered among no less than four different directories is taking two big steps toward complexity.

Credo sia abbastanza chiaro anche così, ma lo traduco qui sotto perché ne condivido ogni parola.

Una delle cose migliori dei sistemi Unix è che la maggior parte delle competenze, dei programmi sviluppati, dei file di configurazione [detti “dot file” perché il nome di questi file inizia in genere con un punto] e degli script di shell sono portatili [su piattaforme differenti]. Io me li sono portati dietro su OS X dopo averli fatti transitare per una dozzina di distribuzioni diverse di Linux…
Di conseguenza mi preoccupa vedere launchd emergere dalla faccia oscura di One Infinite Loop [l’indirizzo della Apple]…
Non ha senso mescolare processi eseguiti periodicamente con il processo principale [di inizializzazione] del sistema operativo. Sostituire un semplice file di testo /etc/crontab con una serie di file plist in formato XML con nomi assurdi e distribuiti su almeno quattro directory diverse è un bel passo avanti [sarebbero due, ma in italiano non viene bene] verso la complessità…

Launchd contro cron

Se consideriamo il semplice obiettivo di rendere automatiche certe attività ripetitive sul Mac, la chiave del discorso sta proprio nell’ultima frase citata: “Sostituire un semplice file di testo /etc/crontab con una serie di file plist in formato XML con nomi assurdi, distribuiti su almeno quattro directory diverse è un bel passo avanti verso la complessità”.

Launchd è molto più complicato di cron, inutilmente più complicato. Basta usarlo un po’ per accorgersene.

Proviamo a sostituire launchd a cron per eseguire lo script ~/bin/makeblog e rigenerare automaticamente il blog “Pazzi per la mela” alle 2:00 di ogni notte.

Con cron basta solo aggiungere al file crontab la riga seguente

00	02	*	*	*	~/bin/makeblog

Se invece si vuole utilizzare launchd, bisogna creare un file plist di configurazione in linguaggio XML più o meno come questo,

<?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>it.pazziperlamela.makeblog</string>
	
	<key>ProgramArguments</key>
	<array>
		<string>/Users/utente/bin/makeblog</string>
	</array>
	
	<key>StartCalendarInterval</key>
	<dict>
		<key>Hour</key>
		<integer>02</integer>
		<key>Minute</key>
		<integer>00</integer>
	</dict>
	
	<key>StandardOutPath</key>
	<string>/Users/utente/Documenti/makeblog.log</string>
	
	<key>StandardErrorPath</key>
	<string>/Users/utente/Documenti/makeblog.err</string>

	<key>RunAtLoad</key>
	<false/>
</dict>
</plist>

salvarlo nella directory ~/Library/LaunchAgents/ del proprio account (la ~ indica la cartella Inizio o home dell’utente che sta usando il Mac) usando obbligatoriamente il nome it.pazziperlamela.makeblog.plist (il nome del file deve essere uguale a quello senza estensione utilizzato alla riga 6 del file plist), e infine eseguirlo una prima volta dal Terminale con il comando

$ launchctl load it.pazziperlamela.makeblog.plist

Per fortuna ai successivi riavvii ci pensa il sistema operativo ad eseguire periodicamente lo script.

Un brevissimo tutorial

Può essere utile descrivere brevemente le informazioni essenziali da inserire nel file plist di configurazione, in modo che il processo automatico gestito da launchd funzioni correttamente. Per ulteriori informazioni, consiglio la lettura di quest’ottimo tutorial e delle specifiche dettagliate del formato del file plist usato da launchd.

Le prime tre righe del file specificano tipo e versione dei formati xml e plist utilizzati, e vanno copiate esattamente come sono scritte nell’esempio precedente.

Il file plist deve contenere tre chiavi obbligatorie. La prima, Label (riga 5), serve per specificare il nome del file plist stesso, senza estensione. Nel nostro caso il nome del file è it.pazziperlamela.makeblog (riga 6).1

La chiave ProgramArguments (riga 8) serve invece per specificare il percorso e il nome dello script di shell da eseguire. Qui è /Users/utente/bin/makeblog, dove al posto di utente bisogna sostituire il nome breve del proprio account. Il modo più semplice per ottenere il proprio nome breve è eseguire da Terminale il comando whoami (oppure id -un).

L’ultima chiave obbligatoria, StartCalendarInterval (riga 13), definisce ora e minuto (oltre che eventualmente giorno della settimana, giorno e mese) in cui launchd deve eseguire lo script di shell. In alternativa si può usare la chiave StartInterval, che lancia invece lo script ogni certo numero di secondi, a partire dalla prima esecuzione del processo tramite launchctl.

Due ulteriori chiavi opzionali, StandardOutPath e StandardErrorPath (righe 21 e 24), definiscono rispettivamente il percorso dei file da usare per salvare l’output completo generato dal comando e gli eventuali messaggi di errore. Anche in questo caso bisogna sostituire nel percorso dei file il proprio nome breve al posto dell’utente generico.

Un’altra utile chiave opzionale è RunAtLoad (riga 27), che specifica se lo script di shell deve essere eseguito al momento del caricamento da parte di launchctl. Questa opzione è inutile se, come in questo caso, si definiscono esattamente gli orari di esecuzione del processo tramite la chiave StartCalendarInterval. Se invece si usa la chiave StartInterval, bisogna impostare RunAtLoad al valore true/, in modo da fissare il tempo iniziale da cui far partire il conteggio dei secondi.

Due comandi utili

Per elencare tutti i processi gestiti da launchd in un dato momento si esegue da Terminale il comando

$ launchctl list

Il Mac su cui sto scrivendo questo post elenca ben 294 processi, considerando sia i processi attivi che quelli ormai terminati.

Per smettere di eseguire automaticamente lo script ` it.pazziperlamela.makeblog.plist`, si deve eseguire il comando

$ launchctl unload ~/Library/LaunchAgents/it.pazziperlamela.makeblog.plist

e poi cancellare (o spostare) il file it.pazziperlamela.makeblog.plist dalla directory ~/Library/LaunchAgents/. In caso contrario, lo script tornerà ad essere lanciato automaticamente al prossimo riavvio.

Conclusioni

È evidente che non mi piace l’idea di usare launchd al posto di cron. Troppo complicato e troppo proprietario. Una vera pugnalata ad uno dei principi cardini di Unix (e del software ben fatto): fare una cosa sola ma farla bene e in modo efficiente.

Intendiamoci, launchd va benissimo per gestire l’avvio del sistema e i servizi automatici (i demoni) gestiti dal sistema operativo e dalla sua introduzione in (Mac) OS X 10.4/Tiger ha reso molto più veloce il processo di avvio di OS X. Ma sostituire launchd a cron introduce un livello di complessità inutile ed insensato.

Nonostante tutto c’è qualcuno a cui launchd piace anche per questo scopo. Contento lui, io finché posso preferisco tenermi stretto il buon vecchio cron.

  1. Il formato consigliato per il nome del file plist è il cosiddetto Uniform Type Identifier (UTI), una struttura simile a quella di un dominio web inverso. In questo caso è stato preso il nome dello script da eseguire makeblog, lo si è aggiunto all’indirizzo del (presunto) sito web del progetto pazziperlamela.it, e infine si è invertito l’ordine della stringa risultante, makeblog.pazziperlamela.it, ottenendo il nome del file plist. 

Sabino Maggi
Pubblicato da Sabino Maggi Segui
Commenti

Aggiungi un commento