有没有办法只在关机时运行脚本?
我的意思是,只有当计算机真正关闭到关闭状态时。仅执行注销或重新启动时,不应运行此脚本。
答案 0 :(得分:16)
几天前我在github上发表了configuration/script able to be executed at boot/shutdown。
基本上在Mac OS X上,您可以/应该将System wide and per-user daemon/agent configuration file
(plist)与bash脚本文件结合使用。这是您可以使用的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>boot.shutdown.script.name</string>
<key>ProgramArguments</key>
<array>
<string>SCRIPT_PATH/boot-shutdown.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>LOG_PATH/boot-shutdown.log</string>
<key>StandardErrorPath</key>
<string>LOG_PATH/boot-shutdown.err</string>
</dict>
</plist>
您可以将此文件放入/Library/LaunchDaemons
。有许多目录可以放置plist文件,这取决于你需要什么,进程的权限等等。
~/Library/LaunchAgents Per-user agents provided by the user.
/Library/LaunchAgents Per-user agents provided by the administrator.
/Library/LaunchDaemons System wide daemons provided by the administrator.
/System/Library/LaunchAgents Mac OS X Per-user agents.
/System/Library/LaunchDaemons Mac OS X System wide daemons.
此脚本boot-shutdown.sh
将在每次启动/关闭时加载并执行。
#!/bin/bash
function shutdown()
{
# INSERT HERE THE COMMAND YOU WANT EXECUTE AT SHUTDOWN OR SERVICE UNLOAD
exit 0
}
function startup()
{
# INSERT HERE THE COMMAND YOU WANT EXECUTE AT STARTUP OR SERVICE LOAD
tail -f /dev/null &
wait $!
}
trap shutdown SIGTERM
trap shutdown SIGKILL
startup;
然后调用加载和卸载守护进程/代理的launchctl
命令。
sudo launchctl load -w /Library/LaunchDaemons/boot-shutdown-script.plist
答案 1 :(得分:3)
这是一种可行的方法(我刚刚测试过),但它非常技术性,不适合没有经验的人......我在/ sbin / shutdown周围放了一个包装器。即使您从GUI中的Apple菜单关闭Mac,这也会有效。
基本上,您需要su
以root身份,并将现有的Apple提供的shutdown
二进制文件重命名为shutdown.orig
。
su -
cd /sbin
mv shutdown shutdown.orig
然后创建一个名为shutdown
的bash脚本,它首先执行您想要的操作,然后execs
原始Apple提供的关闭二进制文件。
#!/bin/bash
Do something you want done before shutdown
exec /sbin/shutdown.orig "$@"
有三件事需要注意......
1. Make all the permissions the same on shutdown as shutdown.orig
2. Parse the parameters to the originl shutdown and see if `-r` is one of them as this means it is a `restart` shutdown. You will also have to pass through the other parameters that Apple calls the script with - if any.
3. Apple may feel at liberty to overwrite your lovely, shiny, new `shutdown` script when updating OSX, so maybe abstract out the bulk of your personal shutdown script into another place so that you can easily re-insert a single-line call to it if/when Apple overwrites it at some point.
小心!并先备份!
答案 2 :(得分:3)
看起来最直接的方法是编写一个小型C ++应用程序,该应用程序将作为带有 launchctl 的守护程序运行,捕获关闭通知但忽略重新启动通知(见下文),然后调用无论作为论据给予什么,例如一个shell脚本。它看起来并不像Apple提供库来捕获任何其他语言的通知。
来自&#34;内核编程&#34;来自Apple的手册https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KernelProgramming/KernelProgramming.pdf,第150页:
&#34;虽然OS X没有传统的BSD式关闭挂钩,但I / O Kit在最新版本中提供了相同的功能。由于I / O Kit提供此功能,因此必须从C ++代码中调用它。&#34;
&#34;要注册通知,请调用registerSleepWakeInterest(在IOKit / RootDomain.h中描述)并注册睡眠通知。如果系统即将关闭,则使用消息类型kIOMessageSystemWillPowerOff调用处理程序。如果系统即将重新启动,则处理程序将获取消息类型kIOMessageSystemWillRestart。如果系统即将重启,则处理程序将获取消息类型kIOMessageSystemWillSleep。&#34;
正如您所看到的,重新启动时会有不同的消息,因此您可以专门处理关闭案例。
答案 3 :(得分:0)
如果有人像我一样通过谷歌搜索类似但有些不同的问题来回答这个问题。
由于我发现的 CopyQ 崩溃错误 https://github.com/hluk/CopyQ/issues/1301 我必须编写一个 cron 脚本,如果它崩溃,它将重新加载。 但是我不想重新加载copyq,如果copyq在关机或重启期间退出
我最终使用了
if ps aux | grep "Finder.app" | grep -v grep
then
echo "I am still running"
else
echo "I am in shutdown"
fi
检测系统是否处于关闭状态(您可以根据需要使用 Chrome.app
或任何其他始终运行的应用程序)
不完全是解决方案,但帮助我解决了我遇到的类似问题