在不使用Logout Hook的情况下在注销时运行脚本


9

我一直在考虑在用户注销时运行一些清理命令,但旧的注销挂钩功能虽然仍在运行,但已经被弃用了一段时间,所以可能不会在我们这么长时间。

不幸的是,虽然 launchd 提供了一个方便的登录挂钩替代方案,没有明显的替代登出挂钩。

我已经尝试过创建一个在登录时启动的shell脚本,只是睡觉直到收到一个kill信号,但是这似乎不起作用(脚本在正常操作期间从不接收信号)。

否则我不确定在注销时运行快速命令的最佳方法是什么?我知道有一些第三方实用程序可以做到这一点,但有没有“正确”的方法来做到这一点?

Answers:


7

似乎Apple对注销挂钩更换不感兴趣,因为他们关闭了我的问题查询一个。

但是,Yosemite的一项改进是现在launchd正确地将信号发送到shell脚本。这意味着您现在可以执行注销任务,如下所示:

这是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

这将简单地休眠(异步,同步地执行而不使用&符号似乎不起作用),直到它收到一个被捕获的信号,此时它将执行 onLogout 功能。

您需要做的就是使用a启动该脚本 RunAtLoad 启动代理或启动守护程序,它将在注销或关闭时运行,但重要的是要记住,任务在被杀之前只有有限的时间来完成,所以这不应该用于运行任何东西这需要很长时间,或者需要可能延迟的网络连接等。

当然这对小牛队或之前的任何人都没有用,但在优胜美地之下,这似乎按预期工作了;所以我实际上是在第一时间做的, launchd 只是没有正确发送信号:)

注意:为了使这个工作,shell脚本似乎需要通过启动直接执行,即 - 它不应该通过调用 sh。所以,如果它被放入 ~/Library/Scripts/foo.sh 您的程序参数可能如下所示:

<key>ProgramArguments</key>
<array>
    <string>~/Library/Scripts/foo.sh</string>
    <string>bar</string>
</array>
<key>EnableGlobbing</key>
<true/>

当我运行此脚本时,它返回 line 8: syntax error near unexpected token ;' (在分号前有一个坟墓)
Jason

哎呀,你是对的@Jason,我觉得我把它简化了太多,我把它调整得更像一个工作的例子。
Haravikk

当我使用launchctl卸载它时会触发它,但是当我退出或重启时则不会触发它。为什么?
Trellis

有没有办法在网络出现故障之前运行它?
user824963

2

您可以使用iHook来运行登录/注销挂钩,我发现它仍适用于在Yosemite上用Bash和Python编写的非交互式登录和注销挂钩。

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


不幸的是,这个仍然使用引擎盖下的正常注销挂钩。
0942v8653

0

如果从搜索引擎到达此处的其他人不关心使用注销挂钩,请运行例如:

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

然后 ~/.logouthook 在您下次注销时运行。

的价值 LogoutHook key必须是可执行文件的路径,而不是shell命令。该 defaults 命令修改 /var/root/Library/Preferences/com.apple.loginwindow.plist


无论如何,感谢您将其作为替代方案,但我担心的是,OS X的最后几个版本已经弃用了登录和注销挂钩;虽然我希望它们仍然在Yosemite中运行(因为它主要集中在UI和Continuity的变化),但似乎它可以随时进行,就像旧的启动项被替换为 launchd,只是一种耻辱,它没有 RunBeforeUnload 或类似的选择。
Haravikk

0

我也无法让launchd注销项在10.10.1中工作,但root的“com.apple.loginwindow.plist”中的LogoutHook键运行良好。 launchd方法还有其他任何示例吗?

无论如何,我写了一个AppleScript来在注销时杀死系统卷,这样下次启动时就不会听到启动响铃。我没有解决的是基于单个LogoutHook键管理多个注销命令的细节,或者是否可以存储多个LogoutHook键,所以我仍然对使用Lingon管理的Launchd方法感兴趣,甚至是Lingon 3,它的范围比原来的要窄得多(可能存在于App商店中)。

set current_Vol to (do shell script "osascript -e \"output volume of (get volume settings)\"")
if button returned of (display dialog "Do you want to silence the startup chime, restore it, or cancel?" buttons {"Silence", "Restore", "Cancel"} default button 1) is "silence" then
    do shell script "mkdir -p  /usr/local/logouttask;echo '#!/bin/bash
# logout script
osascript -e \"set volume 0\"' > /usr/local/logouttask/logoutscript;sudo defaults write com.apple.loginwindow LogoutHook /usr/local/logouttask/logoutscript;chmod +x /usr/local/logouttask/logoutscript" with administrator privileges
else
    try
        do shell script "sudo defaults write com.apple.loginwindow LogoutHook '';rm /usr/local/logouttask/logoutscript" with administrator privileges
        display dialog "The startup chime will be heard if the volume setting is greater than 0 at shut down or restart." buttons {"OK"} default button 1
    on error the error_message number the error_number
        if error_number is 1 then
            display dialog "The script that sets system volume to zero at logout doesn't exist. The startup chime will be heard if the volume setting is greater than 0 at shut down or restart." buttons {"OK"} default button 1
        else
            display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
        end if
    end try
end if

你是如何调用注销项目的?我的示例shell脚本需要直接调用(不使用 sh )所以它需要是一个可执行的文件,我会在我的回答中注意到。
Haravikk

谢谢你的更新。我会尽快尝试并让你知道。
Trellis

我只能通过在终端上调用它的plist上运行“launchctl unload”来触发foo.sh中包含的事件。注销不会触发它。
Trellis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.