1 votos

Cómo ejecutar script usando cron o launchd para la cuenta de usuario Invitado en El Capitan

No he encontrado la forma de ejecutar un script para la cuenta de invitado durante el inicio de sesión que se ejecuta cada minuto. Dicen que usar cron daemon está obsoleto así que parece que usaré launchd con archivos .plist.

Escenario: Tengo un iMac público y quiero permitir que el público en general utilice la cuenta de invitado y que se fuerce el cierre de sesión cada media hora. Escribí un ruby script para comprobar el tiempo de inicio de sesión y calcular el tiempo restante. Puedo hacer que muestre un banner de notificación cada 10 minutos usando osascript y luego hacer que cierre la sesión de mi cuenta. El problema es que cuando intento implementarlo para la cuenta de invitado no funciona.

El problema es cuando coloco el archivo .plist dentro de /Library/LaunchDaemons ya que se ejecuta después de iniciar sesión y también se ejecuta como Root. Ejecutar como Root es importante ya que puedo tener el privilegio de cerrar procesos cuando el tiempo se agota. Necesito que se ejecute una vez cada minuto. Este es el archivo plist actual que funciona cuando me conecto como mi propio nombre de usuario "owner" pero no como invitado. Usando org.user.plist

Mi archivo .plist original tenía el siguiente aspecto

<?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>org.user</string> 
    <key>Program</key> 
        <string>/usr/local/bin/notify-custom</string> 
    <key>RunAtLoad</key> 
        <true/> 
</dict> 
</plist>

Actualización 1 (Todavía no es una solución) .plist que se ejecuta cada 10 segundos tanto para Guest como para mi nombre de usuario

<?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>org.user</string>
    <key>ProgramArguments</key>
        <string>/usr/local/bin/notify-custom</string>
    <key>WatchPaths</key>
        <array>        
            <string>/Users/Guest/Library</string>
            <string>/Users/owner/Library</string>
        <array>
    </integer>
</dict>
</plist>

Como prueba para asegurarme de que el banner de notificación osascript aparece tengo este código dentro de /usr/local/bin/notify-custom

#/bin/bash

#Using whoami would have shown me logged in as root under LaunchDaemon .plist
loggedinUser=`finger | awk 'NR==3{print $1}'`
#I need to manually run terminal and type sudo as guest for nextline to work
sudo -u $loggedinUser /usr/bin/osascript -e 'display notification "Test" with title "Banner Notification"'

La solución está abajo.

1voto

klanomath Puntos 19587

En mi opinión lo siguiente debería funcionar - ¡lo hace en mi VM! - lanzado como /Library/LaunchDaemons/org.user.plist:

<?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>org.user</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/touch</string>
        <string>-f</string>
        <string>/Users/Guest/Desktop/test.txt</string>
    </array>
    <key>UserName</key>
    <string>Guest</string>
    <key>GroupName</key>
    <string>_guest</string>
    <key>InitGroups</key>
    <true/>
    <key>WatchPaths</key>
    <array>
        <string>/Users/Guest/Library</string>
    </array>
</dict>
</plist>

Como tarea de ejemplo utilizo /usr/bin/touch -f /Users/Guest/Desktop/test.txt .

El truco aquí es que todo el contenido de la carpeta de invitados se elimina después de un cierre de sesión. Después de que un nuevo invitado inicie la sesión, todo el contenido se vuelve a crear desde cero. En cuanto se crea la carpeta /Users/Guest/Library, la tarea de ejemplo ( touch ... ) se inicia debido a la clave WatchPaths.

Como la tarea/script/app tiene que ser ejecutada como invitado no se pueden utilizar agentes de lanzamiento porque la ruta /Users/Guest/Library/LaunchAgents/ simplemente no existe.

Utilice un demonio de lanzamiento en su lugar y ejecútelo como Invitado/_invitado . Su ruby script /usr/local/bin/notify-custom tiene que ser legible/ejecutable en el mundo por supuesto.


También he probado a ejecutar la tarea cada 60 segundos, lo que funciona correctamente pero arroja algunos errores después de el cierre de sesión del huésped. Probablemente sea mejor implementar todo en el ruby script. Dependiendo de su script su kilometraje puede variar sin embargo.

Si tienes dos tareas diferentes que ejecutar (por ejemplo, mostrar un banner cada 10 minutos con Ruby y un temporizador para forzar el cierre de sesión después de 30 minutos) probablemente sea mejor crear dos demonios de lanzamiento diferentes.

0voto

Michael Puntos 6

Resuelto. He estado trabajando en esto durante un tiempo. Mi solución finalmente hace lo que necesito y es que se inicia durante el inicio de sesión para el usuario Guest (y como opción también lo tengo iniciando para mí mismo usuario iMac1 sólo para mostrar el tiempo de inicio de sesión). No vi una forma sencilla de poner el archivo org.user.plist en /Users/Guest/Library/LaunchAgents que teóricamente lo habría lanzado cuando el Guest se conectara y la razón por la que me rendí en esa situación es que esa carpeta no se crea hasta el inicio de sesión.

Lo que hice fue poner mi archivo .plist dentro de /Library/LaunchAgents/ que se ejecuta para cada usuario. Eso está bien ya que mi código distinguirá al usuario invitado y tomará una acción (en este caso cerrar la sesión después del tiempo establecido.)

El archivo final .plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
        <string>org.user</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/notify-custom</string>
    </array>
    <key>RunAtLoad</key>
        <true/>
    <key>StartInterval</key>
        <integer>60</integer>
</dict>
</plist>

Fíjate que he añadido una clave RunAtLoad ya que sin ella el script sí se ejecutaba pero esperaba un minuto para disparar su primer evento. Si en lugar de ello utilizara la clave WatchPaths como @klanomath señaló en su comentario, entonces el script se ejecutaría cada 10 segundos ya que debe haber actividad en esa carpeta regularmente. Yo sólo quería que se ejecutara cada 60 segundos por ahora. Puede que cambie ese temporizador más tarde cuando limpie todo el procedimiento con algunos diálogos de advertencia más coloridos escritos en Python.

Aquí está el código ruby dentro de /usr/local/bin/notify-custom que se ejecuta para cada inicio de sesión del usuario:

#!/usr/bin/ruby -w

require 'time'
require 'FileUtils'

loggedinUser=`finger|awk 'END{print $1}'`.strip
getloginTime=`finger|awk 'END{print}'|cut -c49-53`
getnowTime=`date|awk 'NR==1{print $4}'`[0..4]
loginTime=(Time.parse(getloginTime).to_i)
nowTime=(Time.parse(getnowTime).to_i)
diffSec=(nowTime-loginTime)
diffMin=(diffSec/60)
timeRemain=30-diffMin

#To see some console output while debugging
puts "getloginTime      =#{getloginTime}"
puts "getnowTime        =#{getnowTime}"
puts "loginTime=#{loginTime}"
puts "nowTime  =#{nowTime}"
puts "timeRemain=#{timeRemain}"

if loggedinUser == "Guest"
        open("/Users/#{loggedinUser}/Desktop/30 Minutes Max Use Per Day",'a'){|f| f.puts "With this new iMac, you are limited to a maximum of 1/2 hour use per day"}
        if timeRemain < 0
            `/usr/bin/osascript -e 'tell application "Finder" to set desktop picture to POSIX file "/Library/Desktop Pictures/Earth Horizon.jpg"'`
            `/usr/bin/osascript -e 'display notification "SHUTTING DOWN! Now= #{getnowTime}   LoggedInAt=#{getloginTime}   TimeRemain=#{timeRemain}" with title "Guest SHUTTING DOWN" sound name "Glass"'`
            `/usr/bin/osascript -e 'tell app "Terminal" to do script "sudo shutdown -h now"'`
        else
            `/usr/bin/osascript -e 'display notification "Now= #{getnowTime}     TimeRemain=#{timeRemain}" with title "#{loggedinUser} TIME LOGGED IN= #{getloginTime}" subtitle "User= #{loggedinUser}"'`
        end
else
        `/usr/bin/osascript -e 'display notification "Now= #{getnowTime}     TimeRemain=#{timeRemain}" with title "#{loggedinUser} TIME LOGGED IN= #{getloginTime}" subtitle "User= #{loggedinUser}"'`
end

De nuevo, tenga en cuenta que si utiliza los LaunchDaemons en su lugar, éstos se ejecutan bajo la cuenta Root del sistema, mientras que los Agentes se ejecutan en la cuenta de los usuarios conectados. Usando la 2da opción tuve que darle al usuario Invitado permiso para ejecutar sudo shutdown como @klanomath mencionó abajo. Esto se hizo con la ejecución del comando $sudo visudo y añadiendo lo siguiente al final del archivo:

Guest ALL=NOPASSWD: /sbin/shutdown

También quería mostrar sólo la cuenta de invitado en la página de inicio de sesión, así que oculté mi cuenta de esa pantalla con este comando:

sudo dscl . create /Users/hiddenuser IsHidden 1

y si cambias de opinión puedes volver a traerlo con :

sudo dscl . create /Users/hiddenuser IsHidden 0

Gracias @klanomath y @user3439894

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X