I am implementing parental control app via python 3.9 for macOS. Therefore I want to use launch agent to keep my application always alive (app reopened automatically after reboot pc and protected against to be closed via activity monitor.) I want to give keep alive enabling and disabling option to parents that they can deactivate or activate it in the app GUI.
I achieved to keep alive my app standalone signed app without sandboxing(or via Terminal command) but if I sign it with sandbox then I get following error for "launchctl load" and "launchctl bootstrap" commands which are executed in the application "Load failed: 5: Input/output error"
My steps without Sandbox which works fine:
1- Create a com.test_gui.macos.plist file under /Library/LaunchAgents with following content:
`<?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>KeepAlive</key>
<true/>
<key>Label</key>
<string>test_gui</string>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>-g</string>
<string>-a</string>
<string>/Applications/test_gui.app</string>
</array>
</dict>
</plist>`
2- create a python file for launch agent activation (I know either launchctl load or bootstrap should be used but I used both of them to test both.):
import subprocess
cmd = "launchctl enable gui/501/test_gui"
response = subprocess.call(cmd, shell=True)
time.sleep(2)
cmd = "launchctl load -w /Library/LaunchAgents/com.test_gui.macos.plist"
response = subprocess.call(cmd, shell=True)
time.sleep(2)
cmd = "launchctl bootstrap system /Library/LaunchAgents/com.test_gui.macos.plist"
response = subprocess.call(cmd, shell=True)
time.sleep(50)
3- Create standalone app via nutika:
python3.9 -m nuitka --run --standalone --macos-disable-console --macos-create-app-bundle
\--macos-app-mode=ui-element --enable-plugin=pyside6 --macos-app-icon=/Users/emre/Documents/MrProtect/icons/app_icon.png
\--include-data-dir=icons=icons test_gui.py
4-Create a .sh file to sign app without sandboxing:
#!/bin/sh
APP_PATH="/Users/emre/Documents/tests/Deployment/test_gui.app"
SIGNING_IDENTITY_APP="Apple Development: Emre Guenay (***)"
PASSWORD="***"
codesign -s "$SIGNING_IDENTITY_APP" -f \
"$APP_PATH/Contents/MacOS/Python"
codesign -s "$SIGNING_IDENTITY_APP" -f \
"$APP_PATH/Contents/MacOS/test_gui"
exit 0
5-execute sh file and see following output: /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/Python: replacing existing signature /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/test_gui: replacing existing signature
6-copy paste signed standalone app(without sandbox) file under /Applications/
7-execute app and try to close app via activity monitor and observe that the app is reopened automatically. so the launch agent works fine
Failed Steps(Sign the same app with sandbox and observe that both launchctl load and bootstrap returns "Load failed: 5: Input/output error")
8- create an app.entitlements file with following content:
\<?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\>com.apple.security.app-sandbox\</key\>
\<true/\>
\</dict\>
\</plist\>
9-Create a .sh file to sign app with sandboxing:
#!/bin/sh
#
APP_PATH="/Users/emre/Documents/tests/Deployment/test_gui.app"
SIGNING_IDENTITY_APP="Apple Development: Emre Guenay (***)"
PASSWORD="***"
codesign -s "$SIGNING_IDENTITY_APP" -f \
\--entitlements app.entitlements \
"$APP_PATH/Contents/MacOS/Python"
codesign -s "$SIGNING_IDENTITY_APP" -f \
\--entitlements app.entitlements \
"$APP_PATH/Contents/MacOS/test_gui"
exit 0
10-execute sh file and see following output: /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/Python: replacing existing signature /Users/emre/Documents/MrProtect/tests/Deployment/test_gui.app/Contents/MacOS/test_gui: replacing existing signature
11-execute app and try to close app via activity monitor and observe that the app is closed although app started the launch agent.
12-you can re-execute app under /Applications/test_gui.app/Contents/MacOS folder with "./test_gui" or even with sudo "sudo ./test_gui" commands you would see following error message for both launchctl load and bootstrap returns: "Load failed: 5: Input/output error". So if you close the app, it will not be re-opened Moreover console tool launchd.log output shows also (1: Operation not permitted) error for launchctl load and bootstrap commands
My questions:
1-Is there any other method different than launch agent for keep alive? I researched it in internet but I could not find any other method unfortunately. Moreover launch agent is not user friendly anyway, with the reason that sandboxed apps cannot copy paste any files under LaunchAgents folder automatically. I am planning to provide my plist file to users that they can copy paste the file themself into launch agent folder out of sandbox.
2-How can i get rid of "Load failed: 5: Input/output error", thereby I can proceed at least with lanuchctl?
What I have tried additionally:
1-I have also tried to use these linux commands, before executing my sandboxed standalone app file:
sudo -S chown 600 /Library/LaunchAgents/com.test_gui.macos.plist sudo -S chown root:wheel /Library/LaunchAgents/com.test_gui.macos.plist
2-I have already given security fulldisk access to my test_gui app, but it also did not work
My Requirements:
Nuitka: 1.9rc5 Commercial: None Python: 3.9.12 (v3.9.12:b28265d7e6, Mar 23 2022, 18:22:40) Flavor: CPython Official Executable: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 OS: Darwin Arch: x86_64 Version C compiler: /usr/bin/clang (clang).
macOS Sonoma: 14.2.1