Executar script no logout sem usar o gancho de logout

11

Eu estive pensando em executar alguns comandos de limpeza quando um usuário efetua logout, no entanto, o antigo recurso de gancho de logout, embora ainda esteja em funcionamento, está obsoleto há algum tempo, portanto, pode não estar conosco por muito mais tempo.

Infelizmente, embora seja launchduma alternativa conveniente aos ganchos de logon, não existe uma substituição óbvia para os ganchos de logout.

Eu já experimentei criar um script de shell que é iniciado no login e simplesmente dorme até que um sinal de interrupção seja recebido; no entanto, isso parece não funcionar (o script nunca recebe o sinal durante a operação normal).

Caso contrário, não tenho certeza de qual seria a melhor maneira de executar um comando rápido no logout? Eu sei que existem alguns utilitários de terceiros que podem fazer isso, mas existe mais uma maneira "correta" de fazer isso?

Haravikk
fonte

Respostas:

7

Parece que a Apple não está interessada em uma substituição do gancho de logout, pois eles fecharam meu problema perguntando sobre um.

No entanto, uma das melhorias no Yosemite é que o launchd agora envia corretamente sinais para scripts shell. O que isso significa é que agora você pode executar uma tarefa de logoff da seguinte maneira:

Aqui está um exemplo 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

Isso simplesmente dorme (de forma assíncrona, fazê-lo de forma síncrona sem o e comercial não parece funcionar) até receber um dos sinais interceptados, quando executará a onLogoutfunção.

Tudo o que você precisa fazer é iniciar esse script usando um RunAtLoadagente de inicialização ou daemon de inicialização e ele será executado no logout ou desligamento, embora seja importante ter em mente que as tarefas têm apenas um período de tempo limitado para serem concluídas antes de serem mortas. , portanto, isso não deve ser usado para executar nada que demore muito ou exija uma conexão de rede que possa atrasar etc.

É claro que isso não serve para ninguém no Mavericks ou antes, mas sob Yosemite isso agora parece funcionar como esperado; então eu estava realmente fazendo certo, em primeiro lugar, launchdsimplesmente não estava enviando os sinais corretamente :)

NOTA: Para que isso funcione, os scripts do shell parecem precisar ser executados diretamente pelo lançamento, ou seja, não devem ser chamados via sh. Portanto, se ele tiver sido colocado no ~/Library/Scripts/foo.shseu programa, os argumentos podem se parecer com:

<key>ProgramArguments</key>
<array>
    <string>~/Library/Scripts/foo.sh</string>
    <string>bar</string>
</array>
<key>EnableGlobbing</key>
<true/>
Haravikk
fonte
Quando eu executar esse script, ele retorna line 8: syntax error near unexpected token ;'(com uma grave antes do ponto e vírgula)
Jason
Opa, você está certo, Jason, acho que simplifiquei demais, modifiquei para parecer mais um exemplo de trabalho.
Haravikk
Ele é acionado quando eu o descarrego usando o launchctl, mas não quando eu saio ou reinicio. Por quê?
Trellis
Existe uma maneira de executá-lo antes da rede cair?
Filippo
2

Você pode usar o iHook para executar ganchos de logon / logout, que eu descobri que ainda funcionam para ganchos de logon e logoff não interativos escritos em Bash e Python no Yosemite.

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


fonte
Infelizmente, este ainda usa ganchos de logout normais sob o capô.
0942v8653
0

Se outras pessoas que chegam dos mecanismos de busca não se importam em usar um gancho de logout, execute, por exemplo:

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

Em seguida, ~/.logouthooké executado na próxima vez que você sair.

O valor da LogoutHookchave deve ser um caminho para um comando executável e não um shell. O defaultscomando é modificado /var/root/Library/Preferences/com.apple.loginwindow.plist.

Lri
fonte
Obrigado por fornecer como alternativa de qualquer maneira, mas minha preocupação é que os ganchos de logon e logout foram descontinuados nas últimas versões do OS X; embora eu espere que eles ainda funcionem no Yosemite (já que ele é focado principalmente nas alterações na interface do usuário e na continuidade), parece que pode ocorrer a qualquer momento, como os itens de inicialização antigos sendo substituídos por launchd, apenas uma pena que não tenha RunBeforeUnloadou opção semelhante .
Haravikk
0

Também não consigo que o item launchd logout funcione na 10.10.1, mas a chave LogoutHook no "com.apple.loginwindow.plist" do root funciona bem. Existem outros exemplos para o método launchd?

De qualquer forma, escrevi um AppleScript para eliminar o volume do sistema no logout, para que o toque da inicialização não seja ouvido na próxima inicialização. O que ainda não descobri são os detalhes para gerenciar vários comandos de logout com base em uma única chave LogoutHook ou se é possível armazenar várias chaves LogoutHook, por isso ainda estou interessado no método Launchd, que pode ser gerenciado com o Lingon, ou mesmo o Lingon 3, que tem um escopo muito mais restrito que o original (presumivelmente existe na App Store).

defina current_Vol como (faça o shell script "osascript -e \" volume de saída de (obtenha configurações de volume) \ "")
se o botão retornado de (exibir a caixa de diálogo "Deseja silenciar o sinal sonoro de inicialização, restaurá-lo ou cancelar?", os botões {"Silêncio", "Restaurar", "Cancelar"} botão padrão 1) são "silêncio" e depois
    do shell script "mkdir -p / usr / local / logouttask; echo '#! / bin / bash
# logout script
osascript -e \ "defina o volume 0" "> / usr / local / logouttask / logoutscript; os padrões do sudo gravam com.apple.loginwindow LogoutHook / usr / local / logouttask / logoutscript; chmod + x / usr / local / logouttask / logoutscript "com privilégios de administrador
outro
    tentar
        do shell script "padrões do sudo write com.apple.loginwindow LogoutHook ''; rm / usr / local / logouttask / logoutscript" com privilégios de administrador
        display dialog "O toque de inicialização será ouvido se a configuração do volume for maior que 0 ao desligar ou reiniciar." botões {"OK"} botão padrão 1
    em erro, o número da mensagem de erro, o número do erro
        se error_number for 1 então
            display dialog "O script que define o volume do sistema como zero no logout não existe. O toque de inicialização será ouvido se a configuração do volume for maior que 0 ao desligar ou reiniciar." botões {"OK"} botão padrão 1
        outro
            exibir a caixa de diálogo "Erro:" e o número do erro & "." e os botões da mensagem de erro {"OK"} botão padrão 1
        fim se
    tentativa final
fim se
Treliça
fonte
Como você está chamando o item de logout? Meu script de shell de exemplo para precisa ser chamado diretamente (sem uso de sh), portanto ele precisa ser um arquivo executável, observarei isso na minha resposta.
Haravikk
Obrigado pela atualização. Vou tentar o mais rápido possível e informá-lo.
Trellis
Só posso acionar o evento contido no foo.sh executando "launchctl unload" no plist que o chama no Terminal. Sair não o aciona.
Trellis