Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run a script only at shutdown (not log off or restart) on Mac OS X

Is there any way to run a script only at shutdown?

I mean, only when the computer is really shutting down to off state. This script should not run when doing just a log off or restart.

like image 709
Audio01 Avatar asked Jun 13 '14 08:06

Audio01


People also ask

How do I schedule a shutdown on Mac?

On your Mac, choose Apple menu > System Preferences, click Battery , then click Schedule. Select the options you want to use. Schedule a startup or wake time for your Mac: Select the “Start up or wake” checkbox. Choose a day or group of days, enter a time, then click Apply.

What is the difference between log out and shut down on Mac?

The main distinction is that your Mac computer's sleep function does not quit any open processes, whereas the user logout and system shutdown functions quit open processes.

How do I check shutdown logs on Mac?

To view your Mac system logs, launch the Console app. You can launch it with Spotlight search by pressing Command+Space, typing “Console,” and then pressing Enter. You'll also find it at Finder > Applications > Utilities > Console.


2 Answers

Few days ago I published on github a configuration/script able to be executed at boot/shutdown.

Basically on Mac OS X you could/should use a System wide and per-user daemon/agent configuration file (plist) in conjunction with a bash script file. This is a sample of the plist file you could use:

<?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>

You can place this file into /Library/LaunchDaemons. There are many directories where the plist file could be placed, it depends from what you need, the rights of the process and so on.

~/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.

This script boot-shutdown.sh will be loaded and executed at every boot/shutdown.

#!/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;

Then call launchctl command which load and unload daemons/agents.

sudo launchctl load -w /Library/LaunchDaemons/boot-shutdown-script.plist
like image 158
freedev Avatar answered Sep 18 '22 14:09

freedev


It looks like the most straightforward way would be to write a small C++ application that would run as a daemon with launchctl, catch the shutdown notification but ignore the reboot notification (see below) and then call whatever is given to it as arguments, e.g. a shell script. It does not look like Apple provides libraries to catch those notifications in any other language.

From the "Kernel Programming" manual https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KernelProgramming/KernelProgramming.pdf from Apple, page 150:

"Although OS X does not have traditional BSD-style shutdown hooks, the I/O Kit provides equivalent functionality in recent versions. Since the I/O Kit provides this functionality, you must call it from C++ code."

"To register for notification, you call registerSleepWakeInterest (described in IOKit/RootDomain.h) and register for sleep notification. If the system is about to be shut down, your handler is called with the message type kIOMessageSystemWillPowerOff. If the system is about to reboot, your handler gets the message type kIOMessageSystemWillRestart. If the system is about to reboot, your handler gets the message type kIOMessageSystemWillSleep."

As you can see there is a different message for reboot, so you can handle the shutdown case exclusively.

like image 43
Oleg Sklyar Avatar answered Sep 18 '22 14:09

Oleg Sklyar