Come eseguire script usando cron o launchd per l'account utente Guest in El Capitan

1

Non sono riuscito a trovare un modo per eseguire uno script per l'account Guest durante l'accesso che viene eseguito ogni minuto. Dicono che l'uso di cron daemon sia deprecato, quindi sembra che userò launchd con i file .plist.

Scenario: Ho un iMac pubblico Voglio consentire al pubblico di utilizzare l'account guest e farlo forzare a uscire ogni mezz'ora. Ho scritto uno script rubino per controllare il tempo di accesso e calcolare il tempo rimanente. Posso farlo visualizzare una notifica di banner ogni 10 minuti utilizzando osascript e quindi effettuare la disconnessione dal mio account. Il problema è quando cerco di implementarlo per l'account Guest che non funziona.

Il problema si verifica quando inserisco il file .plist in / Library / LaunchDaemons poiché viene eseguito dopo l'accesso e viene eseguito anche come root. L'esecuzione come root è importante poiché posso avere il privilegio di chiudere i processi quando il tempo si esaurisce. Ne ho bisogno per eseguire una volta ogni minuto. Questo è l'attuale file plist che funziona quando effettuo il login come nome utente "proprietario" ma non come ospite. Usando org.user.plist

Il mio file .plist originale era simile a 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>org.user</string> 
    <key>Program</key> 
        <string>/usr/local/bin/notify-custom</string> 
    <key>RunAtLoad</key> 
        <true/> 
</dict> 
</plist>

Aggiornamento 1 (non ancora una soluzione) .plist file che viene eseguito ogni 10 secondi sia per Guest che per il mio nome utente

<?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>

Come test per assicurarmi che il banner di notifica di osascript venga visualizzato ho questo codice in / 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 soluzione è sotto.

    
posta Mickey D 11.08.2016 - 03:12
fonte

2 risposte

0

risolto. Ci sto lavorando da un po '. La mia soluzione finalmente fa ciò di cui ho bisogno e cioè si avvia durante il login per l'utente Guest (e come opzione ho anche l'avvio per me stesso utente iMac1 solo per visualizzare l'ora di login). Non ho visto un modo semplice di mettere il file org.user.plist in / Users / Guest / Library / LaunchAgents che avrebbe teoricamente lanciato quando il Guest ha effettuato l'accesso e il motivo per cui ho rinunciato a quella situazione è dato da quella cartella non è stato creato fino al login.

Quello che ho fatto è stato inserire il mio file .plist in / Library / LaunchAgents / che viene eseguito per ogni utente. Questo va bene dal momento che il mio codice distinguerà l'utente Guest e agirà (in questo caso effettuerà il logout dopo l'orario impostato).

Il file .plist finale:

<?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>

Notate che ho aggiunto una chiave RunAtLoad poiché senza di essa lo script è stato eseguito ma ho aspettato un minuto per sparare il suo primo evento. Se invece avessi usato la chiave di WatchPaths come @klanomath annotata nel suo commento, allora lo script verrebbe eseguito ogni 10 secondi poiché la loro attività deve svolgersi regolarmente in quella cartella. Volevo solo che funzionasse ogni 60 secondi per ora. Potrei cambiare quel timer più tardi quando pulirò l'intera procedura con alcune finestre di avviso più colorate scritte in Python.

Ecco il codice ruby in / usr / local / bin / notify-custom che viene eseguito per ogni accesso utente:

#!/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

Ancora una volta si noti che se si utilizzano i LaunchDaemon, invece, vengono eseguiti nell'account root di sistema mentre gli agenti vengono eseguiti sull'account degli utenti registrati. Usando la seconda opzione ho dovuto dare all'utente il permesso di eseguire sudo shutdown come @klanomath menzionato sotto. Questo è stato fatto eseguendo il comando: $ sudo visudo e aggiungendo quanto segue alla fine del file:

Guest ALL=NOPASSWD: /sbin/shutdown

Inoltre volevo mostrare l'account Guest solo sulla pagina di accesso, quindi ho nascosto il mio account da quella schermata con questo comando:

sudo dscl . create /Users/hiddenuser IsHidden 1

e se cambi idea, puoi riportarlo con:

sudo dscl . create /Users/hiddenuser IsHidden 0

Grazie a @klanomath e @ user3439894

    
risposta data 18.08.2016 - 17:51
fonte
1

Secondo me, dovrebbe funzionare - lo fa nella mia VM! - lanciato come /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>

Come compito di esempio, utilizzo /usr/bin/touch -f /Users/Guest/Desktop/test.txt .

Il trucco qui è che il contenuto completo della cartella Guest viene cancellato dopo una disconnessione. Dopo che un nuovo registro Guest viene ricreato da zero. Non appena viene creata la cartella / Utenti / Guest / Libreria, viene avviata l'attività di esempio ( touch ... ) a causa della chiave WatchPaths.

Poiché l'attività / script / app deve essere eseguita come guest, non è possibile utilizzare gli agent di lancio perché il percorso / Users / Guest / Library / LaunchAgents / semplicemente non esiste.

Utilizza invece un daemon di lancio ed eseguilo come Guest / _guest . Lo script ruby / usr / local / bin / notify-custom deve essere leggibile / eseguibile nel mondo? certo.

Ho anche provato a eseguire l'operazione ogni 60 secondi, il che funziona correttamente ma genera alcuni errori dopo la disconnessione del guest. Probabilmente è meglio implementare il tutto nella sceneggiatura ruby. Tuttavia, a seconda del tuo script, il tuo chilometraggio può variare.

Se hai due compiti diversi da eseguire (es. mostra un banner ogni 10 minuti con Ruby e un timer per forzare la disconnessione dopo 30 minuti) è probabilmente meglio creare due diversi daemon di lancio.

    
risposta data 11.08.2016 - 05:40
fonte

Leggi altre domande sui tag