Não é possível sair do aplicativo iniciado pelo launchd

4

Como se diz no título, "Não é possível sair do aplicativo lançado pelo launchd" - ou, mais precisamente, posso saia, mas depois reinicia automaticamente.


fundo : Eu prefiro usar o BusyCal, não o iCal, mas existem algumas coisas que precisam ser feitas pelo iCal antes que o BusyCal possa obter os resultados. Imaginei criar dois scripts launchd: um para iniciar o iCal todos os dias às 5 da manhã e outro para sair alguns minutos depois.


Aqui está o plist para lançar (em ~/Library/LaunchAgents/com.dori.iCalLaunch.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>KeepAlive</key>
    <false/>
    <key>Label</key>
    <string>com.dori.iCalLaunch</string>
    <key>OnDemand</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
        <string>/Applications/iCal.app/Contents/MacOS/iCal</string>
    </array>
    <key>ServiceDescription</key>
    <string>iCal Launcher</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>5</integer>
    </dict>
</dict>
</plist>

Meu entendimento era que eu não precisava do KeepAlive e OnDemand chaves, mas eu as coloco de qualquer maneira para tentar parar o relançamento.

Aqui está o problema para sair (em ~/Library/LaunchAgents/com.dori.iCalQuit.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>com.dori.iCalQuit</string>
    <key>Program</key>
    <string>/usr/bin/osascript</string>
    <key>ProgramArguments</key>
    <array>
        <string>osascript</string>
        <string>-e</string>
        <string>tell application "iCal" to quit</string>
    </array>
    <key>ServiceDescription</key>
    <string>iCal Quitter</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>5</integer>
        <key>Minute</key>
        <integer>10</integer>
    </dict>
</dict>
</plist>

Com base nos meus arquivos de log, ambos funcionam bem - mas depois que o Quit é executado, o iCal é reiniciado.

Alguma idéia de coisas para tentar, ou coisas que possam estar causando isso?

Dori
fonte

Respostas:

2

Se você não especificar <Minute> no <StartCalendarInterval>então (assim como cron 's * ) irá executar o trabalho a cada minuto.

geekosaur
fonte
Então, por que, quando eu saio do iCal manualmente, ele espera reiniciar até as 5:00 do dia seguinte?
Dori
1
São 6 da manhã ou depois. Para ser pedante: você especificou Hora = 5, mas não Minuto, por isso é executado a cada minuto das 5:00 às 5:59. Se você estivesse acordado durante esse período de tempo e usasse a máquina, não apenas reiniciaria em você, mas também roubaria o foco uma vez por minuto durante a execução. Observe que o seu trabalho de saída especifica Hora e Minuto e não continua sendo executado.
geekosaur
O launchd é construído para iniciar coisas sob demanda, uma vez ou continuamente. Não está configurado para parar as coisas, exceto para sair ou desligar. Como o iCal não possui um mecanismo interno para escutar um comando kill, é melhor carregar e descarregar um trabalho que esteja configurado para ser executado sempre. Veja minha resposta para mais informações ...
bmike
@bmike Mas osascript -e 'tell application "iCal" to quit' funciona. launchd pode não ser projetado para parar tarefas, mas você não explica porque isso não funciona. Além disso, neste caso, launchd não está parando uma tarefa, ela está iniciando uma nova. (Aquele novo acontece de ser um script de shell que pára alguma coisa, mas isso parece estar além do ponto.)
Eu concordo totalmente e perdi a solução mais simples - killall ou osascript. Kudos para @mankoff
bmike
1

Uma resposta para esse problema é um pouco contra-intuitiva.

Simplifique o seu ficheiro iCal plist e faça o iCal funcionar para sempre, definindo OnDemand para false. Aqui está um arquivo que testei armazenando-o como ~/Library/DontLaunchAgents/com.dori.iCalForever.plist - não deixe este arquivo em nenhum diretório que o launchd examine, a menos que você queira iniciar o iCal toda vez que fizer login e reaparecer caso você queira sair do iCal.

<?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>com.dori.iCalForever</string>
    <key>OnDemand</key>
    <false/>
    <key>ProgramArguments</key>
    <array>
        <string>/Applications/iCal.app/Contents/MacOS/iCal</string>
    </array>
</dict>
</plist>

Agora você precisa de um script de shell único que chame esses dois comandos separados por um tempo suficiente para realizar qualquer tarefa que o iCal precise executar.

launchctl load ~/Library/DontLaunchAgents/com.dori.iCalForever.plist
sleep 600 #sleep time in seconds
launchctl unload ~/Library/DontLaunchAgents/com.dori.iCalForever.plist

.. e Bob é seu tio.

bmike
fonte
Eu também acho que você poderia ter dois plots launchd - um para chamar o carregamento de launchctl e outro atrasou para chamar o descarga do launchctl mas eu prefiro a solução de script, uma vez que se comporta melhor se o mac está dormindo e acorda após o tempo de lançamento ter passado. O launchd acionará eventos que devem ter sido executados durante o período de suspensão e você poderá obter a carga e o descarregamento mais rápido do que o desejado nesse caso ímpar.
bmike
0

Algo que você pode querer tentar se configurando isso está se tornando uma dor é Lingon , é fácil de usar editor de GUI para launchd, eu tentaria configurar o seu trabalho nele e ver se você obtém os mesmos resultados.

ConstantineK
fonte
Tão incrível quanto Lingon é - isso não muda a maneira como o launchd funciona. Isso não ajuda com o problema de que o launchd não está configurado para iniciar e parar um aplicativo. O iCal não tem uma maneira fácil de saber que ele deve se matar, então o problema é rastrear o PID do processo do iCal para que ele possa ser descarregado / encerrado assim que o processamento for concluído. Veja minha resposta para mais detalhes.
bmike