Scheduling task via launchctl

I have Time Machine set to start manually as I would prefer to have it do its thing when I'm not at my desk.


To that end, I have created two launchctl plist files, one for a nightly backup, the other for a periodic snapshot. The periodic snapshot works fine; I can see the output in the logs. The nightly backup doesn't work at all, and for the life of me I can't figure out why. Both plist files are in ~/Library/LaunchAgents.


Here's for the backup:


<?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>com.example.TimeMachineBackup</string>
		<key>ProgramArguments</key>
		<array>
			<string>/usr/bin/tmutil</string>
			<string>startbackup</string>
			<string>--auto</string>
		</array>
		<key>StartCalendarInterval</key>
		<dict>
			<key>Hour</key>
			<integer>21</integer>
			<key>Minute</key>
			<integer>00</integer>
		</dict>
		<key>StandardOutPath</key>
		<string>/Users/me/Library/Logs/com.example.TimeMachineBackup.out.log</string>
		<key>StandardErrorPath></key>
		<string>/Users/me/Library/Logs/com.example.TimeMachineBackup.err.log</string>
	</dict>
</plist>


And here's for the snapshot:


<?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>com.example.TimeMachineSnapshot</string>
		<key>ProgramArguments</key>
		<array>
			<string>/usr/bin/tmutil</string>
			<string>localsnapshot</string>
		</array>
		<key>StartInterval</key>
		<integer>3600</integer>
		<key>StandardOutPath</key>
		<string>/Users/me/Library/Logs/com.example.TimeMachineSnapshot.out.log</string>
		<key>StandardErrorPath></key>
		<string>/Users/me/Library/Logs/com.example.TimeMachineSnapshot.err.log</string>
	</dict>
</plist>


For the life of me, I can't figure out why the first one won't run.


Posted on Feb 27, 2024 1:17 PM

Reply
6 replies

Feb 28, 2024 7:39 AM in response to Dolphinslastmessage

Dolphinslastmessage wrote:

What it should do and what it does are two different things.

Well you are the one using the "--auto" flag, which is officially documented as "kinda the same as normal Time Machine, kinda not". So you can't complain about unpredictable behaviour when you're literally using the "-use-unpredictable-behaviour" flag.


Time Machine is a backup utility. Like any backup utility, it's reliability is inversely proportional to how much the user messes with it.

Regardless, I have other maintenance tasks

macOS does not need any maintenance tasks. It is a consumer device designed to take care of itself. Any efforts you put towards changing its default behaviour are going to cause problems for you. 100% guaranteed.

What is now even more frustrating is this:

I made multiple attempts to diagnose this by editing the plist file and changing the start time; no matter what I did, running launchctl print• still showed the original time.
I tried with sudo• and without.
I tried variations of launchctl load/unload and launchctl bootstrap• .
Whatever I was doing yesterday give launchd• the kick in the pants that it needed and the job ran at 21:00 last night as planned.

launchd is a complicated system. If you don't understand how it works, frustration is inevitable.


Use sudo only for system-managed tasks. Traditionally these were located in /Library/LaunchDaemons and /Library/LaunchAgents. In theory, these should be migrated to application bundles in the future.


Don't use the legacy commands like load/unload. Use bootstrap and bootout. This will necessitate learning about launchd domains, which is kinda the point.


Editing plist files does nothing. Those are only persistence files. Only bootstrap and bootout actually modify the launchd system.


Never use the new user interface in Ventura+ System Settings.

Feb 29, 2024 7:18 PM in response to Dolphinslastmessage

Dolphinslastmessage wrote:

If "unpredictable behaviour" includes not running for weeks on end, then there's a problem with Time Machine itself.

That would be a problem with your computer. Time Machine does reliably make backups. Although I do have to admit that I recently had to restore from Time Machine and it didn't work. The machine ran with the previous system, but I encountered numerous instances of filesystem corruption. But I still think having files backed up is valuable and that Time Machine is the best way to do that.

My messing with it is limited to wanting it to run outside my normal use of my laptop. On my prior laptop, Time Machine would slow things down noticeably, and scheduling it as a cron job balanced out my requirements for reliable, periodic backups and a machine that would let me get on with my day.

If you notice Time Machine running, other than by the noise from an external drive perhaps, then you have something seriously wrong elsewhere. Neither cron nor launchd are going to fix that.

I understand from the documentation how it's supposed to work. It's not working the way the documentation suggests, which is why I'm here.

The documentation is sparse and not straightforward.

You clearly don't understand it at all; if you did, you would be trying to help instead of taking cheap shots.

LOL!

My use of sudo was an attempt to diagnose any permission errors that might be getting in the way. If sudo had worked, I would then have moved on to figuring out why and creating a process that didn't require it. It and other attempts at diagnosing the problem didn't work, so I came here.

Yes. That's what I mean. This is one of those cases where sudo isn't going to work. launchd has its own system of domains. Those domains, along with the base permissions system, determine what commands you can run and in what contexts. Even going beyond this specific case, on modern versions of macOS, the "super user" isn't nearly as "super" as it used to be. In some cases, launchctl will suggest running as root for richer errors. It's lying to you.

I'm aware that load/unload are legacy commands. They are not, however, deprecated commands. I tried them for the simple reason that they may behave differently from the modern commands.

They certainly do, but not in a good way. That's why I recommend that you don't use them. They are definitely deprecated. They simply haven't been removed yet.

For example, if I run the following:

launchctl bootstrap gui/501/com.example.TimeMachineBackup

then I think it's reasonable to expect that this:

launchctl print gui/501/com.example.TimeMachineBackup

will output something that will reflect the changes made to the plist file (e.g., changing the trigger time). It did not.

That's because your bootstrap command was wrong. While you are correctly referencing a service target for the user 501 gui domain, that service target either may not exist yet or it may already be loaded. The bootstrap command needs a domain, like "gui/501" and a service path, which is just a path to the plist file. And this is assuming that you had already issued a bootout command to shutdown the service before modifying the config file.


It's curious that you would mention that command without also commenting on the hilarious error message that should result. If you went to the trouble of adding "[sic]" for my auto-corrected apostrophe, you would have (would've?) totally freaked out over that message.

I don't understand this comment at all.

In Ventura and later, Apple added a user interface to kind of control the launchd items. But I strongly suggest that you don't use it. I tell everyone not to use it, but you have extra reasons because you are trying to write your own launchd tasks.


Even when you figure out all the quirky behaviours of launchctl, there is no guarantee that you're ever going to get this working. Time Machine isn't designed to be hacked on by the user. Like launchctl itself, it's been rewritten several times, not always in coordination with documentation updates. Try removing the "--auto" flag and see that works better.

Feb 28, 2024 5:33 AM in response to etresoft

What it should do and what it does are two different things. Regardless, I have other maintenance tasks configured in launchd that aren't running either, and if I can get this one fixed I can get the others fixed as well.


When I run launchctl print, I get output that confirms that the job is scheduled:


	event triggers = {
		com.datadevelopment.TimeMachineBackup.268435469 => {
			keepalive = 0
			service = com.datadevelopment.TimeMachineBackup
			stream = com.apple.launchd.calendarinterval
			monitor = com.apple.UserEventAgent-Aqua
			descriptor = {
				"Minute" => 0
				"Hour" => 21
			}
		}
	}


What is now even more frustrating is this:


  • I made multiple attempts to diagnose this by editing the plist file and changing the start time; no matter what I did, running launchctl print still showed the original time.
    • I tried with sudo and without.
    • I tried variations of launchctl load/unload and launchctl bootstrap.
  • Whatever I was doing yesterday give launchd the kick in the pants that it needed and the job ran at 21:00 last night as planned.

Feb 29, 2024 5:53 PM in response to etresoft


Well you are the one using the "--auto" flag, which is officially documented as "kinda the same as normal Time Machine, kinda not". So you can't complain about unpredictable behaviour when you're literally using the "-use-unpredictable-behaviour" flag.

If "unpredictable behaviour" includes not running for weeks on end, then there's a problem with Time Machine itself. I think it's safe to assume that that's not one of Time Machine's designed behaviours, so that leaves launchd, either the service or my use thereof, as the likely culprit.

Time Machine is a backup utility. Like any backup utility, it's [sic] reliability is inversely proportional to how much the user messes with it.

My messing with it is limited to wanting it to run outside my normal use of my laptop. On my prior laptop, Time Machine would slow things down noticeably, and scheduling it as a cron job balanced out my requirements for reliable, periodic backups and a machine that would let me get on with my day.

macOS does not need any maintenance tasks. It is a consumer device designed to take care of itself. Any efforts you put towards changing its default behaviour are going to cause problems for you. 100% guaranteed.

You have absolutely no idea how I use my machine or what those maintenance tasks are. Suffice it to say that the tasks that I run have nothing to do with the operating system itself. I'm happy to leave macOS to do its thing (minus slowing me down while doing a backup), while still using its documented capabilities to automate things that I need automated.

launchd is a complicated system. If you don't understand how it works, frustration is inevitable.

I understand from the documentation how it's supposed to work. It's not working the way the documentation suggests, which is why I'm here. You clearly don't understand it at all; if you did, you would be trying to help instead of taking cheap shots.

Use sudo only for system-managed tasks. Traditionally these were located in /Library/LaunchDaemons and /Library/LaunchAgents. In theory, these should be migrated to application bundles in the future.

My use of sudo was an attempt to diagnose any permission errors that might be getting in the way. If sudo had worked, I would then have moved on to figuring out why and creating a process that didn't require it. It and other attempts at diagnosing the problem didn't work, so I came here.

Don't use the legacy commands like load/unload. Use bootstrap and bootout. This will necessitate learning about launchd domains, which is kinda the point.

I'm aware that load/unload are legacy commands. They are not, however, deprecated commands. I tried them for the simple reason that they may behave differently from the modern commands. As with sudo, had they worked, I would have then tried to figure out what they were doing differently from the modern commands in order to get my configuration to work the modern way.

Editing plist files does nothing. Those are only persistence files. Only bootstrap and bootout actually modify the launchd system.

That's lovely in theory, and aligns with what the documentation implies. However, running them against my plist files returns no error message and doesn't modify launchd in any way that suggests that they're actually doing anything.


For example, if I run the following:


launchctl bootstrap gui/501/com.example.TimeMachineBackup


then I think it's reasonable to expect that this:


launchctl print gui/501/com.example.TimeMachineBackup


will output something that will reflect the changes made to the plist file (e.g., changing the trigger time). It did not.

Never use the new user interface in Ventura+ System Settings.

I don't understand this comment at all.



[Edited by Moderator] 


This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Scheduling task via launchctl

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.