Mac daemon not able to run bash script
Originally asked on Stack Overflow, but it may be more suited for here. Wherever it’s answered first, I’ll be sure to update the counterpart question with the same answer.
I've already checked this similar question.
OS MacOS 10.15.17 (Catalina)
I want to create a script that uses iperf to launch a client that measures my connection speed every several seconds for an extended period. I’ve created a daemon file and put it in ~/Library/LaunchAgents/com.myself.iperfclient.plist
.
com.myself.iperfclient.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">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.myself.iperfclient</string>
<key>ProgramArguments</key>
<array>
<string>/Users/myself/Documents/bin/iperf/netspeed</string>
</array>
<key>StartInterval</key>
<integer>20</integer> <!-- in seconds -->
<key>Disabled</key>
<false/>
</dict>
</plist>
netspeed
#!/bin/bash
# see https://stackoverflow.com/a/246128/10200417
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
script_name=`basename $0`
# echo "called script $script_name from $script_dir"
iperf_server=127.0.0.1
iperf_port=54321
# launch iperf client, log results to ./logs/client.log
iperf \
-c $iperf_server \
-p $iperf_port \
--logfile $script_dir/logs/client.log
The netspeed
file is executable for anyone:
$ ls -l netspeed
-rwxr-xr-x@ 1 myself staff 379 Jan 11 21:36 netspeed
When I try to add the new daemon, with launchctl load ~/Library/LaunchAgents/com.myself.iperfclient.plist
, this is the error message I get in the Console:
Sandbox: bash(50654) System Policy: deny(1) file-read-data /Users/myself/Documents/bin/iperf/netspeed
If in the .plist
descriptor for the daemon I add <string>open</string>
as the first item in ProgramArguments
, there’s no error. However, I don’t want to run the script this way because it launches a new Terminal window every time, which is extremely annoying.
My question
How do I allow my daemon process to execute netspeed
?
P.S.
The launchctl status code is 126.
$ launchctl list | grep myself
- 126 com.myself.iperfclient
Solution 1:
Alright, here’s what I ended up doing, which does work and doesn’t require any other installations. I tried the answer from Gilby, but wasn’t able to get fdautil to work after downloading and installing it via the LaunchControl trial version.
If it had worked, it seems it would have done so by granting LaunchControl’s fdautil utility full disk access, which would then use those permissions somehow to execute my netspeed
script (without passing those permissions to /bin/bash
?).
Method 1: AppleScript wrapper
I created Users/myself/Documents/bin/iperf/netspeed.scpt
, which has the following:
do shell script "/Users/myself/Documents/bin/iperf/netspeed"
I then updated the ProgramArguments entry in the launchd plist to:
<key>ProgramArguments</key>
<array>
<string>/usr/bin/osascript</string>
<string>/Users/myself/Documents/bin/iperf/netspeed.scpt</string>
</array>
Finally, in System Preferences > Security and Privacy > Files and Folders
I was able to grant access for Users/myself/Documents
to /usr/bin/osascript
, and successfully launch the daemon.
Method 2: Put script in location with less security
As @user3439894 pointed out, since the main reason it was difficult to execute netspeed
in the first place was that I had it in ~myself/Documents.../
, which has elevated permissions requirements, I can also just put it in a location with less security.
I followed the suggestion to try /Users/Shared/.../netspeed
and it indeed worked with my original script and plist contents! To be clear, the ProgramArguments would now be:
<key>ProgramArguments</key>
<array>
<string>/Users/Shared/.../netspeed</string>
</array>