How To Create Services in macOS using $Bash — launchctl, and plutil Commands — Step-by-Step Guide!
Do you want to understand how services are created in macOS? How does your macOS know that you have installed an application? How does it know how long your screen time is ON? All is through background services!!
In this article, we will cover some of the key features of launchctl
and how to use it to manage services in macOS. We will discuss how to use launchd
and plutil
to create and configure services, and how to convert property list files to different formats. By using the tools and techniques described in this article, you can create and manage services in macOS, and automate tasks and scripts to run automatically and efficiently.
That said, let’s dive right into the article, to create a service in macOS using bash, you can use the automator
tool to create a new service. The reason why we choose $bash
is to directly interact with the kernel of any OS without any built-in libraries.
[How To Create A Service]
- Open
Automator
from yourApplications
folder. - Select
Service
from the list of document types. - In the top search bar, type
Run Shell Script
and double-click the result to add it to the workflow. - From here, you can customize the service by writing your desired bash commands in the Run Shell Script action. For example, if you want to create a service that backs up a file or folder to a specified directory, you could use the following
$bash
script:
#!/bin/bash
# Get the file or folder that the service is being run on
input=$(cat)
# Set the directory where the backup should be saved
backup_dir=~/Desktop/Backups
# Create the backup directory if it does not exist
if [ ! -d "$backup_dir" ]; then
mkdir -p "$backup_dir"
fi
# Create a timestamp for the backup
timestamp=$(date +%Y-%m-%d_%H-%M-%S)
# Create the backup file
cp -R "$input" "$backup_dir/$timestamp-backup"
Once you have finished configuring your service, you can save it and give it a name. This will run the $bash
script and create a backup of the file or folder in the specified directory.
To use the service
, you can right-click on a file or folder in Finder and select your service from the contextual menu.
To customize the service, you can add additional actions to the workflow by dragging them from the left-hand panel and dropping them into the workflow on the right. For example, you could add an Ask for Finder Items
action to prompt the user to select one or more files or folders before running the shell script.
When configuring the Run Shell Script
action, you can choose whether to pass input to the script as arguments or as standard input. You can also choose whether to show the output of the script in a new window or to speak the output using the built-in text-to-speech capabilities of macOS.
Once you have finished configuring your service, you can save it by clicking File
> Save
and giving it a name. The service will be saved to the ~/Library/Services
folder and will be available from the contextual menu in Finder. You can also access and manage your services by opening Automator
and selecting Services
from the top menu.
NOTE: After you have saved your service, you can test it by right-clicking on a file or folder in Finder and selecting your service from the contextual menu. If your service is working correctly, it should run the bash commands that you specified in the run Shell Script
action.
One thing to keep in mind when creating services in macOS is that they can only be used to automate tasks that can be performed on a single item at a time. For example, if you want to run a $bash
script that processes multiple files, you will need to create a separate service for each file.
Additionally, you can use the automator
tool to create services that can be triggered using keyboard shortcuts. To do this, you can add a Launch Application
or Run AppleScript
action to your workflow and specify the keyboard shortcut that you want to use to trigger the service. This can make it easier to access your services without having to use the contextual menu in Finder.
[launchd]
In addition to using the automator
tool to create services, you can also create services using the launchd
utility in macOS. This utility allows you to run scripts and other programs automatically at specified intervals or at specific times. To create a service using launchd
, you will need to create a property list file (also known as a plist file) that contains the configuration settings for your service.
<?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.backup-service</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>
# Get the file or folder that the service is being run on
input=$(cat)
# Set the directory where the backup should be saved
backup_dir=~/Desktop/Backups
# Create the backup directory if it does not exist
if [ ! -d "$backup_dir" ]; then
mkdir -p "$backup_dir"
fi
# Create a timestamp for the backup
timestamp=$(date +%Y-%m-%d_%H-%M-%S)
# Create the backup file
cp -R "$input" "$backup_dir/$timestamp-backup"
</string>
</array>
<key>StartInterval</key>
<integer>3600</integer>
</dict>
</plist>
As far as the above backup service
example is concerned, the Label
key specifies the unique identifier for your service, and the ProgramArguments
key specifies the $bash
script that you want to run as your service. Also, the service will run the script every
hour (3600 seconds) and create a backup of the selected file or folder.
The property list file should be saved in the ~/Library/LaunchAgents
directory and should have a filename in the following format: <label>.plist
, where <label>
is a unique identifier for your service. The property list file should contain the following keys:
Label
: This is the unique identifier for your service. It should match the filename of your property list file, without the .plist
extension.ProgramArguments
: This is an array of strings that specifies the command or script that you want to run as your service.StartInterval
: This is an integer that specifies the number of seconds between each time your service is run. This key is only used if you want your service to be run at regular intervals.StartCalendarInterval
: This is a dictionary that specifies the exact date and time when your service should be run. This key is only used if you want your service to be run at a specific time.
To run your service using launchd
, you can use the launchctl
command to load the property list file that you created. For example, if your property list file is called myService.plist
and is saved in the ~/Library/LaunchAgents
directory, you can use the following command to load it:
#Command
launchctl load ~/Library/LaunchAgents/myService.plist
Once your property list file is loaded, launchd
will automatically run your service according to the configuration settings that you specified in the property list file. You can use the launchctl
command to start, stop, and manage your service, as well as view the status of your service and any errors that may have occurred.
In summary, there are two ways to create services in macOS: using the automator
tool or using the launchd
utility. Both methods allow you to automate tasks and run scripts automatically, but launchd
offers more advanced options for scheduling and managing services.
One important thing to keep in mind when using launchd
to create services is that your property list file must be in the correct format and must contain all of the required keys. If your property list file is not formatted correctly, launchd
will not be able to run your service.
[plutil]
To ensure that your property list file is formatted correctly, you can use the plutil
command to validate it. For example, if your property list file is called myService.plist
, you can use the following command to validate it:
#Command
plutil -lint myService.plist
If your property list file is valid, plutil
will return no output. If there are any errors in your property list file, plutil
will display them and provide details about what is wrong and how to fix it. For example, if your property list file is missing the Label key, plutil
will output the following error:
#Error
myService.plist: The key 'Label' is missing.
By using the plutil
command to validate your property list file, you can ensure that your service is set up correctly and will run without any issues.
In addition to using plutil
to validate your property list file, you can also use it to convert your property list file to a different format. By default, property list files in macOS are saved in binary format, but you can use plutil
to convert them to XML or JSON format.
To convert a property list file from binary to XML or JSON format, you can use the -convert
option with plutil
. For example, if you want to convert a property list file called myService.plist
from binary to XML format, you can use the following command:
#Command
plutil -convert xml1 myService.plist
If the conversion is successful, plutil
will create a new file called myService.xml that contains the same data as the original property list file, but in XML format. You can then edit the XML file using a text editor, and use plutil
to convert it back to binary format when you are finished.
Converting property list files to XML or JSON format can be useful if you want to share your property list files with others, or if you want to use a different tool to edit your property list files. By using plutil to convert your property list files, you can ensure that they are in the correct format and will work with launchd
and other tools in macOS.
[launchctl]
In addition to using launchd
and plutil
to manage services in macOS, you can also use the launchctl
command to control and manage your services. With launchctl
, you can start, stop, and restart your services, as well as view the status of your services and any errors that may have occurred.
To start a service using launchctl
, you can use the start subcommand followed by the Label
of the service that you want to start. For example, if the Label
of your service is com.example.myservice
, you can use the following command to start it:
#Command
launchctl start com.example.myservice
If your service is started successfully, launchctl
will return no output. If there are any errors, launchctl
will display them and provide details about what went wrong. For example, if your service is already running, launchctl
will output the following error:
#Response
com.example.myservice: Already loaded
By using launchctl
to start your services, you can ensure that they are running and will be able to perform the tasks that you have configured them to do.
In addition to starting your services, you can also use launchctl
to stop and restart them. To stop a service using launchctl
, you can use the stop
subcommand followed by the Label of the service that you want to stop. For example, if the Label
of your service is com.example.myservice
, you can use the following command to stop it:
#Command
launchctl stop com.example.myservice
If your service is stopped successfully, launchctl
will return no output. If there are any errors, launchctl
will display them and provide details about what went wrong. For example, if your service is not currently running, launchctl
will output the following error:
#Error
com.example.myservice: Could not find specified service
By using launchctl
to stop your services, you can ensure that they are not running and will not consume any system resources. This can be useful if you want to temporarily disable a service, or if you want to stop
a service before making changes to its configuration.
To restart a service using launchctl
, you can use the stop
and start
subcommands together. For example, if the Label of your service is com.example.myservice
, you can use the following command to stop and then restart it:
#Command
launchctl stop com.example.myservice && launchctl start com.example.myservice
This command will first stop the service, and then start it again. By using this command, you can quickly restart a service without having to stop and start it separately. This can be useful if you want to apply changes to a service’s configuration without having to manually stop and start it.
In addition to starting, stopping, and restarting your services, you can also use launchctl
to view the status of your services and any errors that may have occurred. To view the status
of a service using launchctl
, you can use the list
subcommand followed by the Label
of the service that you want to view. For example, if the Label
of your service is com.example.myservice
, you can use the following command to view its status:
#Command
launchctl list com.example.myservice
If your service is running and there are no errors, launchctl
will display information about the service, including its Label
, PID (process ID)
, and Status
. For example, the output of the list
subcommand might look like this:
#Response
{
"Label" = "com.example.myservice";
"PID" = 12345;
"Status" = "Running";
}
If there are any errors with your service, launchctl
will display them along with the Label
of the service. For example, if your service is not currently running, launchctl
will output the following error:
#Error
com.example.myservice: Could not find specified service
By using the list
subcommand, you can quickly check the status of your services and see if they are running properly. This can be useful if you want to troubleshoot any issues with your services or if you just want to see if they are running as expected.
To conclude, the launchctl
is a powerful tool for managing services in macOS. With launchctl
, you can start
, stop
, and restart
your services, as well as view the status of your services and any errors that may have occurred. By using launchctl
in combination with launchd
and plutil
, you can easily create and manage services in macOS, and automate tasks and scripts to run automatically at specified intervals or at specific times.
Thanks for reading!! If you enjoyed this article, please follow and subscribe for the latest updates. Looking for more? Check out the other posts below: