在不使用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.