4

Given a shell script that calls the macOS screencapture utility, a proper screenshot (meaning, a full capture of what is on the screen, including any application windows visible) is produced when calling that shell script from the terminal. However, using launchd to periodically call the same script does not produce the desired result, in this case the screenshot only shows an empty desktop background and a menu bar. I am running macOS 12.5 Monterey.

My desired goal is to automatically take screenshots by using launchd to call a shell script periodically. I specifically want to call a shell script or unix executable file, and do not want to use cron or any application other than launchd for scheduling purposes. My actual screenshot shell script is more involved than in the example. In the past I have been able to successfully load other daemons calling shell scripts as in the example through launchctl, but never ran into permission problems like this before.

Example

screenshot.sh

#!/bin/zsh

# save as `~/Library/bin/screenshot.sh`
# make executable by ways of the following command: `chmod +x ~/Library/bin/screenshot.sh`

screencapture -C ~/Desktop/test$( date +'%H%M%S' ).png;

Save this script in ~/Library/bin/ and make it executable by calling chmod +x. Note that calling running this script works fine if Terminal.app (or equivalent...) has been given screen recording permissions (see 'Permissions' below).

com.example.screenshot.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">
<!--
  save as `~/Library/LaunchAgents/com.example.screenshot.plist`
  load this by ways of the following command: `sudo launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.screenshot.plist`
  unloading this: `sudo launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.example.screenshot.plist`
-->
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.example.screenshot</string>

    <!-- replace <<USERNAME>> with the actual username -->
    <key>Program</key>
    <string>/Users/<<USERNAME>>/Library/bin/screenshot.sh</string>

    <key>StartInterval</key>
    <integer>10</integer>

    <key>ProcessType</key>
    <string>Background</string>

    <key>StandardErrorPath</key>
    <string>/tmp/launchd.example.screenshot_stderr.log</string>
    <key>StandardOutPath</key>
    <string>/tmp/launchd.example.screenshot_stdout.log</string>
  </dict>
</plist>

First, make sure that under <key>Program</key> <USERNAME> is set to your actual username, or that the path to the screenshot.sh file is absolute. Save this .plist in ~/Library/LaunchAgents/ and load by calling sudo launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.screenshot.plist. Unloading works by changing the subcommand to bootout. The launchctl manpage can be found here.

Permissions

Screen recording permissions can be given to applications in System Preferences → Security & Privacy → Privacy → Screen Recording → '+'. Adding Terminal.app to this list, and restarting the application gives proper screenshots when calling screenshot.sh directly from the terminal. I have tried adding /bin/launchd, /bin/launchctl, /usr/sbin/screencapture, Terminal.app, and the screenshot script (saved without the .sh suffix) to the list of allowed apps and then rebooting, but I am still not able to produce proper screenshots through launchd.

Question in short

For the set-up given above, what settings do I change or permissions do I give such that I get proper screenshots that show open applications?

Questions pertaining to the same problem have been asked here and here, but the answers aren't satisfactory (don't work or don't use launchd).

1 Answer 1

5

Have been working on the same thing and finally figured it out after much digging and testing.

I noticed in the CoreServices there is a launchservicesd app. I added this to Screen Recording permissions and it works.

It's located exactly here: /System/Library/CoreServices/ and you're looking for exactly launchservicesd to give permissions to.

For others reading this not knowing how to add these to Screen Recording, you need to use Command+Shift+G to bring up a Go menu in the Preferences to pick these specific locations.

In total you will need to have Screen Recording permissions for all of the following:

/bin/bash

/System/Library/CoreServices/launchservicesd

/usr/sbin/screencapture

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .