Exécuter le script à la déconnexion sans utiliser le crochet de déconnexion

11

J'ai cherché à exécuter quelques commandes de nettoyage lorsqu'un utilisateur se déconnecte.Cependant, l'ancienne fonctionnalité de déconnexion, bien qu'elle fonctionne toujours, est obsolète depuis un certain temps et ne sera peut-être pas avec nous plus longtemps.

Malheureusement, bien qu'il launchdoffre une alternative pratique aux crochets de connexion, il n'y a pas de remplacement aussi évident pour les crochets de déconnexion.

J'ai déjà expérimenté la création d'un script shell qui est lancé lors de la connexion et qui se met simplement en veille jusqu'à ce qu'un signal d'arrêt soit reçu, mais cela ne semble pas fonctionner (le script ne reçoit jamais le signal pendant le fonctionnement normal).

Sinon, je ne sais pas quelle serait la meilleure façon d'exécuter une commande rapide lors de la déconnexion? Je sais qu'il existe des utilitaires tiers qui peuvent le faire, mais existe-t-il une façon "correcte" de le faire?

Haravikk
la source

Réponses:

7

Il semble qu'Apple ne soit pas intéressé par un remplacement du crochet de déconnexion, car ils ont clos mon problème en me renseignant sur l'un d'entre eux.

Cependant, l'une des améliorations de Yosemite est que launchd envoie désormais correctement les signaux aux scripts shell. Cela signifie que vous pouvez maintenant effectuer une tâche de déconnexion comme suit:

Voici un exemple logout.sh:

#!/bin/sh
onLogout() {
    echo 'Logging out' >> ~/Logs/logout.sh.log
    exit
}

trap 'onLogout' SIGINT SIGHUP SIGTERM
while true; do
    sleep 86400 &
    wait $!
done

Cela dormira simplement (de manière asynchrone, le faire de manière synchrone sans l'esperluette ne semble pas fonctionner) jusqu'à ce qu'il reçoive l'un des signaux piégés, auquel cas il exécutera la onLogoutfonction.

Tout ce que vous avez à faire est de lancer ce script à l'aide d'un RunAtLoadagent de lancement ou d'un démon de lancement et il s'exécutera à la déconnexion ou à l'arrêt, bien qu'il soit important de garder à l'esprit que les tâches n'ont qu'un temps limité à terminer avant d'être tuées. , donc cela ne devrait pas être utilisé pour exécuter quoi que ce soit qui prend beaucoup de temps, ou nécessite une connexion réseau qui pourrait être retardée, etc.

Bien sûr, cela ne sert à personne sur Mavericks ou plus tôt, mais sous Yosemite cela semble maintenant fonctionner comme prévu; donc je le faisais bien en premier lieu, launchdje n'envoyais pas les signaux correctement :)

REMARQUE: Pour que cela fonctionne, les scripts shell semblent devoir être exécutés directement par lancé, c'est-à-dire qu'ils ne doivent pas être invoqués via sh. Donc, s'il était placé dans ~/Library/Scripts/foo.shvotre programme, les arguments pourraient ressembler à ceci:

<key>ProgramArguments</key>
<array>
    <string>~/Library/Scripts/foo.sh</string>
    <string>bar</string>
</array>
<key>EnableGlobbing</key>
<true/>
Haravikk
la source
Lorsque j'exécute ce script, il revient line 8: syntax error near unexpected token ;'(avec une tombe avant le point-virgule)
Jason
Oups, vous avez raison @ Jason, je pense que je l'ai trop simplifié, je l'ai peaufiné pour ressembler davantage à un exemple de travail.
Haravikk
Il se déclenche lorsque je le décharge à l'aide de launchctl, mais pas lorsque je me déconnecte ou redémarre. Pourquoi?
Trellis
Existe-t-il un moyen de l'exécuter avant que le réseau ne tombe en panne?
filippo
2

Vous pouvez utiliser iHook pour exécuter des hooks de connexion / déconnexion, ce qui, selon moi, fonctionne toujours pour les hooks de connexion et de déconnexion non interactifs écrits en Bash et Python sur Yosemite.

http://rsug.itd.umich.edu/software/ihook/


la source
Malheureusement, celui-ci utilise toujours des crochets de déconnexion normaux sous le capot.
0942v8653
0

Si d'autres personnes qui arrivent ici à partir des moteurs de recherche ne se soucient pas d'utiliser un hook de déconnexion, exécutez par exemple:

sudo defaults write com.apple.loginwindow LogoutHook '~/.logouthook';echo $'#!/usr/bin/env bash\n\nsay a'>~/.logouthook;chmod +x ~/.logouthook

Il ~/.logouthookest ensuite exécuté la prochaine fois que vous vous déconnectez.

La valeur de la LogoutHookclé doit être un chemin d'accès à un exécutable et non une commande shell. La defaultscommande se modifie /var/root/Library/Preferences/com.apple.loginwindow.plist.

Lri
la source
Merci de l'avoir proposé comme alternative de toute façon, mais mon inquiétude est que les crochets de connexion et de déconnexion sont obsolètes pour les dernières versions d'OS X; bien que je m'attende à ce qu'ils fonctionnent toujours dans Yosemite (car il est principalement axé sur les modifications de l'interface utilisateur et de la continuité), il semble que cela puisse aller à tout moment, comme les anciens éléments de démarrage remplacés par launchd, juste une honte qu'il n'a pas RunBeforeUnloadou une option similaire .
Haravikk
0

Je ne peux pas non plus faire fonctionner l'élément de déconnexion de launchd dans 10.10.1, mais la clé LogoutHook dans "com.apple.loginwindow.plist" de root fonctionne bien. Y a-t-il d'autres exemples pour la méthode launchd?

Quoi qu'il en soit, j'ai écrit un AppleScript pour tuer le volume du système à la déconnexion afin que le carillon de démarrage ne soit pas entendu au prochain démarrage. Ce que je n'ai pas trouvé, ce sont les détails de la gestion de plusieurs commandes de déconnexion basées sur une seule clé LogoutHook, ou s'il est possible de stocker plusieurs clés LogoutHook, donc je suis toujours intéressé par la méthode Launchd, qui pourrait être gérée avec Lingon, ou même Lingon 3, qui a une portée beaucoup plus étroite que l'original (vraisemblablement pour exister dans l'App Store).

définissez current_Vol sur (faire le script shell "osascript -e \" volume de sortie de (obtenir les paramètres de volume) \ "")
si le bouton est revenu de (afficher la boîte de dialogue "Voulez-vous désactiver le carillon de démarrage, le restaurer ou annuler?" boutons {"Silence", "Restaurer", "Annuler"} bouton par défaut 1) est "silence" puis
    faire le script shell "mkdir -p / usr / local / logouttask; echo '#! / bin / bash
# script de déconnexion
osascript -e \ "set volume 0 \" '> / usr / local / logouttask / logoutscript; sudo écrit par défaut com.apple.loginwindow LogoutHook / usr / local / logouttask / logoutscript; chmod + x / usr / local / logouttask / logoutscript "avec des privilèges d'administrateur
autre
    essayer
        faire le script shell "sudo par défaut écrire com.apple.loginwindow LogoutHook ''; rm / usr / local / logouttask / logoutscript" avec des privilèges d'administrateur
        boîte de dialogue d'affichage "Le carillon de démarrage sera entendu si le réglage du volume est supérieur à 0 à l'arrêt ou au redémarrage." boutons {"OK"} bouton par défaut 1
    en cas d'erreur, le numéro de message d'erreur, le numéro d'erreur
        si error_number est 1 alors
            boîte de dialogue d'affichage "Le script qui définit le volume du système à zéro à la déconnexion n'existe pas. Le carillon de démarrage sera entendu si le paramètre de volume est supérieur à 0 à l'arrêt ou au redémarrage." boutons {"OK"} bouton par défaut 1
        autre
            afficher la boîte de dialogue "Erreur:" & le numéro_erreur & "." & les boutons message_erreur {"OK"} bouton par défaut 1
        fin si
    fin de l'essai
fin si
Treillis
la source
Comment invoquez-vous l'élément de déconnexion? Mon exemple de script shell pour doit être appelé directement (pas d'utilisation de sh) donc il doit s'agir d'un fichier exécutable, je le noterai dans ma réponse.
Haravikk
Merci d'avoir mis à jour. J'essaierai dès que possible et je vous le ferai savoir.
Trellis
Je ne peux déclencher l'événement contenu dans foo.sh qu'en exécutant "launchctl unload" sur le plist qui l'appelle dans Terminal. La déconnexion ne le déclenche pas.
Trellis