Mon CV

Alerter un utilisateur si son compte mobile n’est pas synchronisé

17 juin 2013

Si vous gérez un parc de Macs autour d’un serveur à la pomme, peut-être utilisez-vous la configuration “compte mobile” pour certains de vos utilisateurs. Cette configuration permet d’avoir un répertoire de départ synchronisé entre un dossier réseau (AFP ou NFS) et le poste client. C’est particulièrement adapté aux utilisateurs nomades (portables) qui ne peuvent pas forcément démarrer sur un compte réseau lorsqu’ils ne sont pas sur votre réseau.

Le souci, c’est que rien ne vous garanti que vos utilisateurs sont à jour de leurs synchronisations,  d’autant qu’il est facile, au boot, d’annuler la synchronisation du compte.

Une première chose est de réaliser périodiquement un petit audit pour savoir si vos comptes mobiles sont à jour côté serveur. Je vous ai présenté cela il y a quelques temps.

Une deuxième idée, qui m’est venue en voyant que certains utilisateurs étaient un poil récalcitrants, est de faire preuve de pédagogie et de les alerter.

L’idée centrale est de vérifier cette fois côté client si les paramètres de synchronisation du compte sont corrects. Si c’est OK, rien ne se passe (transparent pour l’utilisateur), si par contre nous détectons un problème nous affichons un message. Nous allons pour cela nous attarder sur le fichier ~/Library/Preferences/com.apple.homeSync.plist. Ce fichier contient plusieurs informations importantes :

  • homeSyncTime contient la dernière date de synchronisation, c’est l’information qui nous permets de savoir si une synchronisation du compte mobile a été effectuée récemment,
  • loginSyncCompleted nous indique par false ou true si une synchronisation complète du compte mobile a été effectuée lors de la dernière ouverture de session,
  • logoutSyncCompleted nous indique par false ou true si une synchronisation complète du compte mobile a été effectuée lors de la dernière fermeture de session.

Pour ma part je considère qu’il y a problème :

  • si le homeSyncTime date de plus de 5 jours,
  • si loginSyncCompleted et logoutSyncCompleted sont tous deux sur false.

Pour réaliser cela je suis passé par Automator qui me permets de réaliser une partie en Shell et une partie en AppleScript (pour avoir les fenêtres de dialogue).

 

Les étapes

Grosso modo, voici ce que je fais :

  • Je commence par un script Shell …
  • Je vérifie déjà si ~/Library/Preferences/com.apple.homeSync.plist existe : s’il n’existe pas, je termine mon processus (ou plutôt je revoie vers la sortie standard une valeur qui sera interprétée ensuite par mon AppleScript), car cela indique que je ne suis pas en présence d’un compte mobile,
  • Je fais une copie temporaire de ~/Library/Preferences/com.apple.homeSync.plist dans ~/Library/AlerteHomeSync/tmp (en créant préalablement les dossiers s’ils n’existent pas), pour pouvoir travailler dessus sans corrompre le fichier en cas de problème,
  • Je réalise une conversion de ce fichier temporaire ~/Library/AlerteHomeSync/tmp/com.apple.homeSync.plist au format xml1 grâce à la commande plutil -convert (le fichier original est au format plist binaire),
  • J’exploite le champ homeSyncTime en le convertissant en secondes et en ajoutant 5 jours (c’est une variable que vous pouvez modifier) pour le comparer à la date du jour et savoir si la dernière synchronisation a été réalisée dans mon laps de temps de “tolérance”. Il y a  plein de manières d’extraire la variable homeSyncTime, ici je le fais avec awk. Je mets le résultat de mon test dans une variable que je reverrai ensuite à mon AppleScript (la variable ETAT_SYNC prend comme valeur 0 si problème),
  • J’extrait la valeur de la chaine loginSyncCompleted et logoutSyncCompleted avec la même méthode. Je mets le résultat de mes deux tests dans une variable que je reverrai ensuite à mon AppleScript (la variable SOMME_BOOL prend comme valeur 0 si les deux tests sont négatifs, 1 si un des deux est positif, 2 si les deux sont positifs),
  • Je supprime mon dossier temporaire ~/Library/AlerteHomeSync/tmp/,
  • Je revoie avec un simple echo mes deux dernières variables (ETAT_SYNC et SOMME_BOOL),
  • Je continue en AppleScript pour avoir de jolies fenêtres de dialogue sans trop me casser la tête …
  • Je récupère en entrée standard les valeurs de variables qui m’intéressent suite à mes tests en Shell (ETAT_SYNC et SOMME_BOOL),
  • Si la date de ma dernière synchronisation est trop ancienne je propose à l’utilisateur de redémarrer son poste pour synchroniser son compte,
  • Si SOMME_BOOL=”0″, je suppose qu’il y a un problème et je propose à l’utilisateur de déposer un ticket sur le gestionnaire d’incidents. Vous pourrez adapter l’action à réaliser …

J’ai oublié une chose : je journalise ce qui se passe du côté de mon script Shell dans ~/Library/AlerteHomeSync/AlerteHomeSync.log.

 

Le script shell

Pour créer ce Workflow, ouvrez donc Automator.app, et choisissez de créer une application. Cette application sera composée de deux actions (à faire glisser depuis la liste d’actions) :

  • Exécuter un script Shell,
  • Exécuter un script AppleScript.

Automator1

Dans le contenu du script Shell intégrez le code suivant en bash (en le modifiant si besoin, notamment au niveau des variables) :

NB_JOURS_TEST=5
SEC_TEST=$(($NB_JOURS_TEST*24*60*60))
DIR=~/Library/AlerteHomeSync
LOG=$DIR/AlerteHomeSync.log
TMP_DIR=$DIR/tmp
PLIST=~/Library/Preferences/com.apple.homeSync.plist
PLIST_NAME=$(basename $PLIST)
TMP_PLIST=$TMP_DIR/$PLIST_NAME

[ ! -f $PLIST ] && echo "PLIST_ABSENT" && exit 0

[ -d $TMP_DIR ] && rm -R $TMP_DIR

mkdir -p $DIR
mkdir -p $TMP_DIR

echo "****************************** $(date) ******************************" >> $LOG

# Copie dans un dossier temporaire et décodage du binaire plist
cp $PLIST $TMP_DIR/
plutil -convert xml1 $TMP_PLIST

# Transformation de la date du fichier plist en secondes puis comparaison avec 
DATE_PLIST=$(awk -F"[<>]" '/homeSyncTime/ {getline;print $3;exit}' $TMP_PLIST)
DATE_SEC=$(date -j -f "%Y-%m-%dT%TZ" "$DATE_PLIST" "+%s")
DATE_SEC_PLUS=$(($DATE_SEC+$SEC_TEST))

if [ $DATE_SEC_PLUS -gt $(date "+%s") ] 
	then
	echo "Date de derière synchronisation correcte : $DATE_PLIST" >> $LOG
	ETAT_SYNC=1
else 
	echo "Date de derière synchronisation du répertoire de départ trop ancienne ($DATE_PLIST) !"  >> $LOG
	ETAT_SYNC=0
fi

# cherchons les lignes contenant les entrées loginSyncCompleted et logoutSyncCompleted
ETAT_LOGIN=$(awk '/loginSyncCompleted/ {getline;print;exit}' $TMP_PLIST | grep -c "true")
[ $ETAT_LOGIN -eq 0 ] && echo "L'état \"loginSyncCompleted\" n'est pas correct" >> $LOG
ETAT_LOGOUT=$(awk '/logoutSyncCompleted/ {getline;print;exit}' $TMP_PLIST | grep -c "true")
[ $ETAT_LOGOUT -eq 0 ] && echo "L'état \"logoutSyncCompleted\" n'est pas correct" >> $LOG
SOMME_BOOL=$(($ETAT_LOGOUT+$ETAT_LOGIN))

# Vidons le dossier temporaire
rm -R $TMP_DIR

# renvoi des variables : 0=erreur
echo $ETAT_SYNC 
echo $SOMME_BOOL

exit 0

 

Côté AppleScript

Côté AppleScript (votre deuxième fenêtre) vous pouvez adapter et coller le code suivant :

on run {input, parameters}
	activate
	set ETAT_SYNC to item 1 of input
	if ETAT_SYNC ≠ "PLIST_ABSENT" then
		set SOMME_BOOL to item 2 of input
		if ETAT_SYNC = "0" then
			set RESTART to button returned of (display dialog "Votre compte mobile n'est pas correctement synchronisé. Merci de redémarrer votre session pour effectuer une synchronisation." with icon 1 buttons {"Redémarrer", "Plus tard"} default button {"Redémarrer"})
			if RESTART = "Redémarrer" then
				tell application "System Events" to restart
			end if
		else
			if SOMME_BOOL = "0" then
				set TICKET to button returned of (display dialog "Votre compte mobile n'est pas correctement synchronisé. Merci de déposer un ticket auprès de votre administrateur." with icon 1 buttons {"Ticket", "Plus tard"} default button {"Ticket"})
				if TICKET = "Ticket" then
					open location "http://url.de.votre.gestionnaire.de.tickets"
				end if
			end if
		end if
	end if
end run

 

L’ensemble devrait ressembler à cela :

 Automator2

 

Vous pouvez tester le Workflow, puis faites un petit cmd+s pour enregistrer l’ensemble (moi je l’ai mis dans /usr/local/AlerteHomeSync/ après avoir créé le dossier, mais vous pouvez le déposer simplement dans le dossier /Applications.

 

Pour démarrer tout cela :

Pour lancer tout cela, je suis parti sur un LaunchAgent situé dans /Library/LaunchAgent/ qui lance mon Application Automator toutes les 5 heures et à l’ouverture de session. L’intérêt est que l’application sera ainsi lancée avec l’utilisateur en cours, ce qui permet d’avoir les bonnes autorisations d’accès au répertoire home (et notamment ~/Library/AlerteHomeSync/ et ~/Library/Preferences/com.apple.homeSync.plist).

Voici le contenu du fichier name.gdo.serveur.alertehomesync.plist (le chemin est à adapter si vous mettez votre application ailleurs) :

<?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>name.gdo.serveur.alertehomesync</string>
	<key>Program</key>
	<string>/usr/local/AlerteHomeSync/AlerteHomeSync.app/Contents/MacOS/Application Stub</string>
	<key>RunAtLoad</key>
	<true/>
	<key>StartInterval</key>
	<integer>14400</integer>
</dict>
</plist>

 

Redémarrez ensuite votre session pour vérifier que ce plist se charge bien au démarrage puis consulter le journal ~/Library/AlerteHomeSync/AlerteHomeSync.log pour être sûr que le processus fonctionne.

 

Evidemment, vous pouvez créer un package avec l’ensemble pour le déployer sur tous vos postes. Dans ce cas, pensez à demander à faire un logout de la session a la fin de l’installation pour forcer à charger le LaunchAgent avec l’utilisateur concerné.

 

Les commentaires sont ouverts pour améliorer l’ensemble si vous voyez de choses à redire !

Posted in Apple et Macintosh, Unix et LinuxTags: