#macos #periodic #schedule #repeat

launchd

Rust library for creating and parsing launchd files

3 releases (breaking)

0.3.0 Aug 8, 2023
0.2.0 Mar 26, 2021
0.1.0 Mar 23, 2021

#314 in Unix APIs

Download history 3/week @ 2024-07-18 35/week @ 2024-07-25 14/week @ 2024-09-19 6/week @ 2024-09-26

165 downloads per month

MIT license

51KB
1K SLoC

launchd

A Rust library for creating and parsing Launchd files.

Disclaimers

It's still in early development and all help is welcome.

The syntax for building launchd files is still subject for change. Launchd has a lot of properties, and I'm considering using derive_builder or something similar to reduce boilerplate code, and increase maintainability. I'm hoping to have made that decision by v0.4.0. Suggestions are welcome!

The Launchd struct is not yet complete. The fields are not public by design, so I can add (but not delete) fields through patches, without the need to create a new minor version.

This library is largely untested. This is not a huge issue for the majority of the program. The only real issue is with the cron feature.

I'm still thinking about what should happen if uninitialized CalendarIntervals are added to the struct. Should an exception be thrown, should they silently be filtered out, or should I leave that responsibility to the user. For now it's your own responsibility, but that behaviour might change in the future.

FAQ

What is Launchd?

Launchd is MacOS's way of scheduling programs and services to be ran.

For more information: Wiki.

For a more detailed description of the parameters run man launchd.plist on your Apple computer or check out: manpagez or xcode-man-pages.

Why not cron?

MacOS deprecated cron, the previous way of scheduling programs.

This library also provides a way of parsing crontabs to CalendarIntervals when the cron feature is selected. Disclaimer: this feature is still untested.

Why not systemd?

Due to licensing issues MacOS does not support systemd. The parsing of systemd is not included in this library.

Usage

Add this to your Cargo.toml dependencies:

launchd = "0.3.0"

Features

Default

launchd = {version = "0.3.0", features=["io"]}

Translate crontabs

launchd = {version = "0.3.0", features=["cron"]}

Without the plist writer

launchd = {version = "0.3.0", default-features = false, features=["serde"]}

Example

use std::path::Path;
use launchd::{CalendarInterval, Error, Launchd};
fn main() -> Result<(), Error> {
    let ci = CalendarInterval::default()
        .with_hour(12)?
        .with_minute(10)?
        .with_weekday(7)?;

    let launchd = Launchd::new("LABEL", Path::new("./foo/bar.txt"))?
            .with_user_name("Henk")
            .with_program_arguments(vec!["Hello".to_string(), "World!".to_string()])
            .with_start_calendar_intervals(vec![ci])
            .disabled();
    
    launchd.to_writer_xml(std::io::stdout())
}

Results in:

<?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>LABEL</string>
        <key>Disabled</key>
        <true />
        <key>UserName</key>
        <string>Henk</string>
        <key>Program</key>
        <string>./foo/bar.txt</string>
        <key>ProgramArguments</key>
        <array>
                <string>Hello</string>
                <string>World!</string>
        </array>
        <key>StartCalendarIntervals</key>
        <array>
                <dict>
                        <key>Minute</key>
                        <integer>10</integer>
                        <key>Hour</key>
                        <integer>12</integer>
                        <key>Weekday</key>
                        <integer>7</integer>
                </dict>
        </array>
</dict>
</plist>

Dependencies

~0.3–6MB
~37K SLoC