Ejecutar secuencia de comandos al cerrar sesión sin usar el gancho de cierre de sesión

Estuve buscando ejecutar algunos comandos de limpieza cuando un usuario cierra la sesión, sin embargo, la antigua función de enlace de cierre de sesión, aunque todavía funciona, ha quedado obsoleta desde hace algún tiempo, por lo que es posible que no esté con nosotros por mucho más tiempo.

Desafortunadamente, aunque launchdproporciona una alternativa conveniente a los ganchos de inicio de sesión, no existe un reemplazo tan obvio para los ganchos de cierre de sesión.

Ya experimenté con la creación de un script de shell que se inicia al iniciar sesión y simplemente duerme hasta que se recibe una señal de interrupción; sin embargo, esto no parece funcionar (el script nunca recibe la señal durante el funcionamiento normal).

De lo contrario, no estoy seguro de cuál sería la mejor manera de ejecutar un comando rápido al cerrar la sesión. Sé que hay algunas utilidades de terceros que pueden hacerlo, pero ¿hay alguna forma "correcta" de hacerlo?

Respuestas (4)

Parece que Apple no está interesado en un reemplazo de enlace de cierre de sesión, ya que cerraron mi problema preguntando por uno.

Sin embargo, una de las mejoras en Yosemite es que launchd ahora envía correctamente las señales a los scripts de shell. Lo que esto significa es que ahora puede realizar una tarea de cierre de sesión como esta:

Aquí hay un ejemplo 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

Esto simplemente dormirá (asincrónicamente, hacerlo sincrónicamente sin el ampersand no parece funcionar) hasta que reciba una de las señales atrapadas, momento en el que ejecutará la onLogoutfunción.

Todo lo que necesita hacer es ejecutar ese script usando un RunAtLoadagente de lanzamiento o un demonio de lanzamiento y se ejecutará al cerrar la sesión o apagarlo, aunque es importante tener en cuenta que las tareas solo tienen una cantidad limitada de tiempo para completarse antes de que se eliminen. , por lo que esto no debe usarse para ejecutar nada que lleve mucho tiempo o requiera una conexión de red que pueda retrasarse, etc.

Por supuesto, esto no es útil para nadie en Mavericks o antes, pero en Yosemite ahora parece funcionar como se esperaba; así que en realidad lo estaba haciendo bien en primer lugar, launchdsimplemente no estaba enviando las señales correctamente :)

NOTA: Para que esto funcione, parece que los scripts de shell deben ejecutarse directamente al iniciarse, es decir, no debe invocarse a través de sh. Entonces, si se colocara en ~/Library/Scripts/foo.shsu programa, los argumentos podrían verse así:

<key>ProgramArguments</key>
<array>
    <string>~/Library/Scripts/foo.sh</string>
    <string>bar</string>
</array>
<key>EnableGlobbing</key>
<true/>
Cuando ejecuto este script, regresa line 8: syntax error near unexpected token ;'(con una tumba antes del punto y coma)
Vaya, tienes razón @Jason, creo que lo simplifiqué demasiado, lo modifiqué para que se parezca más a un ejemplo de trabajo.
Se activa cuando lo descargo usando launchctl, pero no cuando cierro sesión o reinicio. ¿Por qué?
¿Hay alguna manera de ejecutarlo antes de que la red se caiga?

Puede usar iHook para ejecutar ganchos de inicio/cierre de sesión, que he descubierto que aún funcionan para ganchos de inicio y cierre de sesión no interactivos escritos en Bash y Python en Yosemite.

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

Desafortunadamente, este todavía usa ganchos de cierre de sesión normales debajo del capó.

Si a otros que llegan aquí desde los motores de búsqueda no les importa usar un gancho de cierre de sesión, ejecute, por ejemplo:

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

Luego ~/.logouthookse ejecuta la próxima vez que cierre la sesión.

El valor de la LogoutHookclave tiene que ser una ruta a un ejecutable y no un comando de shell. El defaultscomando modifica /var/root/Library/Preferences/com.apple.loginwindow.plist.

Gracias por darlo como alternativa de todos modos, pero mi preocupación es que los ganchos de inicio y cierre de sesión han quedado obsoletos para las últimas versiones de OS X; aunque espero que todavía funcionen en Yosemite (ya que se centra principalmente en la interfaz de usuario y los cambios de continuidad), parece que podría funcionar en cualquier momento, como los elementos de inicio antiguos reemplazados por launchd, es una pena que no tenga RunBeforeUnloaduna opción similar .

Tampoco puedo hacer que el elemento de cierre de sesión de launchd funcione en 10.10.1, pero la tecla LogoutHook en "com.apple.loginwindow.plist" de root funciona bien. ¿Hay otros ejemplos para el método launchd?

De todos modos, escribí un AppleScript para matar el volumen del sistema al cerrar la sesión para que el timbre de inicio no se escuche en el próximo inicio. Lo que no he resuelto son los detalles para administrar múltiples comandos de cierre de sesión basados ​​en una sola clave LogoutHook, o si es posible almacenar varias claves LogoutHook, por lo que todavía estoy interesado en el método Launchd, que podría administrarse con Lingon, o incluso Lingon 3, que tiene un alcance mucho más limitado que el original (presumiblemente existirá en la tienda de aplicaciones).

establezca current_Vol en (haga el script de shell "osascript -e \"volumen de salida de (obtenga la configuración de volumen)\"")
si el botón regresó (diálogo de visualización "¿Desea silenciar el timbre de inicio, restaurarlo o cancelar?" botones {"Silenciar", "Restaurar", "Cancelar"} botón predeterminado 1) es "silencio" entonces
    ejecute el script de shell "mkdir -p /usr/local/logouttask;echo '#!/bin/bash
# script de cierre de sesión
osascript -e \"establecer volumen 0\"' > /usr/local/logouttask/logoutscript;sudo defaults write com.apple.loginwindow LogoutHook /usr/local/logouttask/logoutscript;chmod +x /usr/local/logouttask/logoutscript " con privilegios de administrador
más
    intentar
        haga el script de shell "sudo defaults write com.apple.loginwindow LogoutHook '';rm /usr/local/logouttask/logoutscript" con privilegios de administrador
        mostrar el cuadro de diálogo "Se escuchará el timbre de inicio si la configuración de volumen es mayor que 0 al apagar o reiniciar". botones {"OK"} botón predeterminado 1
    en caso de error el número del mensaje de error el número de error
        si error_number es 1 entonces
            mostrar el cuadro de diálogo "La secuencia de comandos que establece el volumen del sistema en cero al cerrar la sesión no existe. El timbre de inicio se escuchará si la configuración del volumen es mayor que 0 al apagar o reiniciar". botones {"OK"} botón predeterminado 1
        más
            mostrar el cuadro de diálogo "Error: " & el error_number & ". " & los botones de mensaje de error {"OK"} botón predeterminado 1
        terminara si
    intento final
terminara si
¿Cómo está invocando el elemento de cierre de sesión? Mi secuencia de comandos de shell de ejemplo debe invocarse directamente (sin uso de sh), por lo que debe ser un archivo que sea ejecutable, lo anotaré en mi respuesta.
Gracias por actualizar Probaré lo antes posible y te cuento.
Solo puedo desencadenar el evento contenido en foo.sh ejecutando "launchctl unload" en el plist que lo llama en Terminal. Cerrar sesión no lo activa.