Making Mac OSX launchctl launch a process as root on startup - macos

My question is how to make a MacOSX daemon process using launchd start with root privileges automatically after a reboot?
I'm writing an application for in house use that blocks access to web sites. It is written in python and modifies the /ect/hosts file to disable or enable listed urls. The main application is in django and I created a python twisted daemon that does the actual modification of the /etc/hosts file as root access privileges are required.
I have created a plist file which works with one minor issue. After rebooting the daemon process has my normal logon privileges instead of root privileges.
A workaround is to stop the process with my normal privileges then startup the process with sudo.
launchctl unload /Library/LaunchAgents/com.balanceinfosystems.socialshields.twisted.plist
sudo launchctl load /Library/LaunchAgents/com.balanceinfosystems.socialshields.twisted.plist
The plist file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.balanceinfosystems.socialshields.twisted</string>
<key>Program</key>
<string>/source/social_shields/social_shields_twisted.py</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>

You've put this in the wrong directory. LaunchAgents are processes run per-user. System processes go in /Library/LaunchDaemons. They are run as root. If you want this to run at startup, I recommend making that explicit with:
<key>RunAtLoad</key>
<true/>

Related

How do I write a script that restarts an application that runs in the Terminal on Mac server after the machine reboots?

I have an application that normally runs in Terminal. This requires changing directory to the application directory [cd /mydirectory] and launching the application ./PurplesoftServer
I am struggling with writing a launch script to restart the application if the server restarts for any reason. I saved the script in /Library/LaunchAgents
This is my script:
```<?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>PSM.Restart</string>
<key>ProgramArguments</key>
<array>
<string>/Users/stephenjay/Documents/HW/HW Customers/ACME server 200814</string>
<string>./PurpleSoftServer</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>```
I also ran the following commands in Terminal in an effort to load the script:
sudo launchctl load /Library/LaunchAgents/PSM.Restart.plist
sudo launchctl start PurplesoftServer
Everything appears to run - after I gave ownership of the plist to root:wheel
However, the application doesn't end up running, neither after running the Sudo commands nor after actually restarting the Mac server.
What have I missed?
The first item in the ProgramArguments array should be the path to the executable, not a directory to cd to. You need to use the WorkingDirectory key instead. Something like this:
...
<key>ProgramArguments</key>
<array>
<string>./PurpleSoftServer</string>
</array>
<key> WorkingDirectory</key>
<string>/Users/stephenjay/Documents/HW/HW Customers/ACME server 200814</string>
...
BTW, you'll need to use sudo launchctl unload to unload the bad version, then sudo launchctl load again to load the fixed version.
BTW2, sudo launchctl list PSM.Restart will give you more info about the run status of the item.

Launchd task unloads when computer restarts

I have a simple launchd plist file that I am using to run a shell script that is designed to restart the computer:
<?xml vesion="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.sag95.restartscript</string>
<key>KeepAlive</key>
<false/>
<key>RunAtLoad</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/Users/sag95/Desktop/Scripts/restartscript.sh</string>
</array>
<key>StartInterval</key>
<integer>300</integer>
</dict>
</plist>
The script file is a single line force restart command(password in real file, not placed here):
echo <password> | sudo -S shutdown -r now
Once I load the plist file using
launchctl load com.sag95.restartscript.plist
it appears in the list (launchctl list). Currently I have the plist file to run the script every 5 minutes. After the 5 minutes of loading, the script is called the first time and subsequently restarts the computer. Once I login, the launchd plist file is no longer in the list (launchctl list). I waited 30 minutes and it hasn't run again to restart my computer.
My question is why is the com.sag95.restartscript plist file unloading after the restart/force reboot?
launchctl load only loads it for the current session. Next time you log in, it loads your list of launch agents from /System/Library/LaunchAgents/*.plist, /Library/LaunchAgents/*.plist, and /Users/sag95/Library/LaunchAgents/*.plist. If the file isn't in one of these folders, it will not get loaded.
Assuming you want it to run only when you are logged in, place the file in /Users/sag95/Library/LaunchAgents. If you wanted it to run for any logged in user, put it in /Library/LaunchAgents instead (but with this specific script, the password will only work for your account, so this wouldn't be useful).

Launchd runs with manual "launchctl start", but not on StartCalendarInterval

I have a very simple Launch Daemon, com.daily.vocab.plist, which simply runs a basic script. It is supposed to run every day at a certain time (using StartCalendarInterval), but I can't get that to happen. Many posts online are saying it runs a minute or two off, but for me it just never runs.
I have been setting the run time to be 5 minutes in the future while I am testing, and now have it set to run at the 0th second of every minute, just so I can get it to work. Once it's working, I will set it to my desired daily run time.
As advised in this tutorial, it is saved in /Library/LaunchDaemons. I loaded it manually with launchctl load /Library/LaunchDaemons/com.daily.vocab.plist. I do in fact see it has loaded when I run launchctl list. When I manually tell it to run with launchctl start com.daily.vocab, it works immediately as expected. The only issue is that the StartCalendarInterval seems to be ignored. I am on Mavericks on my Macbook.
Here is the file: com.daily.vocab.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.daily.vocab</string>
<key>Program</key>
<string>/Users/MGS/developer/projects/vocab-sms/scripts/DEvocab.sh</string>
<key>StartCalendarInterval</key>
<dict>
<key>Second</key>
<integer>0</integer>
</dict>
</dict>
</plist>
Ideally, I believe I want it to run at 7:15am every day making the StartCalendarInterval section be instead:
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>15</integer>
</dict>
If you could even share an example of a LaunchDaemon you got to work using StartCalendarInterval and every step you made to make it work (e.g. running launchctl load x.x.x.plist), that would be really helpful!
Solution: This local daemon should actually be a user agent, so it needed to be saved in and loaded from the ~/Library/LaunchAgents directory. From there, I also needed to unload the agent and reload the agent.
NOTE: Daemons/Agents do not automatically update in launchd until you unload/load. You can't just save the updated .plist and expect it to work!
launchd plists saved in /Library/... are daemons / agents in the local domain and have to be loaded with sudo. Without sudo you're loading the daemon in the user domain which doesn't match the actual path.
Since you are calling a script in the user domain anyway, save the script in ~/Library/LaunchAgents (it's not a daemon). The plist syntax is supposed to be correct.
will have to change the permission for the bash file
chmod u+v /Users/MGS/developer/projects/vocab-sms/scripts/DEvocab.sh

Start ngrok automatically on OSX

I am trying to start ngrok automatically when my mac mini starts up. I thought maybe OSX had something like the init-folder on ubuntu where you place scripts you want to start automatically, but i haven't found anything like it.
Are there no way to just run commands on startup on OSX?
You can create a LaunchDaemon to run ngrok on startup (or a LaunchAgent if you want to start ngrok after a user logs in). See the apple docs.
A LaunchDaemon is a plist that resides in /Library/LaunchDaemons/. For example, my LaunchDaemon (/Library/LaunchDaemons/com.ngrok.onstartup.plist) looks something like this:
<?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.ngrok.onstartup</string>
<key>Program</key>
<string>/path/to/ngrokd</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
The choice of the Label is up to you as long as it uniquely identifies your daemon. In this example my LaunchDaemon is called com.ngrok.onstartup.
ngrokd is a bash script looking like this:
#!/bin/sh
/usr/local/bin/ngrok -log=/path/to/ngrok.log -config=/path/to/ngrok.yml start ssh
You can check that launchd started your daemon by typing:
sudo launchctl list com.ngrok.onstartup

Sonatype Nexus - Service not starting on launch - MAC

Okay so following the instructions here
http://books.sonatype.com/nexus-book/reference/install-sect-service.html
I take the example plist file
<?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.sonatype.nexus</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/nexus/bin/nexus</string>
<string>console</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
and stick it in my /Library/LaunchDeamons folder (I have also tries /System/Library/LaunchDeamons to no avail).
I have set the permissions on the file as specified in the documentation and I can even load the file manually using :
sudo launchctl load /Library/LaunchDaemons/com.sonatype.nexus.plist
However this does not start the service.
I can start the Nexus instance manually using this command from the terminal.
/usr/local/nexus/bin/nexus console
However on reboot of the device this service is not being launched and I still have to go back into the Terminal and manually call the command to start the Nexus instance.
Can anyone point me in a direction that might fix this? (Brand new to LaunchDeamons)
The console output is shown
Thanks
Aiden
This is most likely a permissions issue. The two options you have are to run Nexus as root user. This is not advisable for servers but might be okay for your local development purposes.
If thats the case you have to set the RUN_AS_USER in the nexus startup script to root and have Nexus installed in a folder root has access to (any really therefore) .. I suggest to use /opt
Better would be to create a specific user e.g. named 'nexus' and set the RUN_AS_USER to that name and make sure the user has full access to the Nexus installation (nexus folder and sonatype work folder).

Resources