I am creating a macOS installer package.
For this I am using a post-install script file that launches an application and then loads a LaunchDaemon plist.
Here is the post-install script:
#!/bin/bash
cd /usr/local/TestApp
USER_NAME=$(who | head -1 | head -1 | awk '{print $1;}')
sudo -u $USER_NAME /usr/local/TestApp/Test.app/Contents/MacOS/Test -l
sudo launchctl load /Library/LaunchDaemons/com.testapp.plist
The result is that it starts the application with the sudo -u $USER_NAME /usr/local/TestApp/Test.app/Contents/MacOS/Test -l
command and then blocks, because the application keeps running.
Therefore, the script gets stuck, and the LaunchDaemon is never loaded.
Please let me know what I can do this in case.
If you simply want to launch a Mac application (*.app
) asynchronously,
open -a
with the bundle directory path (ending in .app
)--args
(see man open
):sudo -u $USER_NAME open -a /usr/local/TestApp/Test.app --args -l
See note at the bottom re reliably determining $USER_NAME
, the invoking user's username.
If, for some reason, you do need to target the executable embedded in the *.app
bundle directly, you must use Bash's &
control operator to run the command in the background:
#!/bin/bash
# Get the underlying username (see comments below).
userName="${HOME##*/}"
# Launch the app in the background, using control operator `&`
# which prevents the command from blocking.
# (Given that the installer runs the script as the root user,
# `sudo` is only needed here for impersonation.)
sudo -u "$userName" /usr/local/TestApp/Test.app/Contents/MacOS/Test -l &
# Load the daemon.
# (Given that the installer runs the script as the root user,
# `sudo` is not needed here.)
launchctl load /Library/LaunchDaemons/com.testapp.plist
Note that I've changed the way that the underlying username is determined:
${HOME##*/}
extracts the last path component from $HOME
, the underlying user's home directory path, which reflects the user who invoked the installer.
This is more robust than using who
without arguments, whose output can include other users.
(As an aside, who | head -1 | head -1 | awk '{print $1;}'
can be simplified to the more efficient who | awk '{print $1; exit}
).