As part of my rollout of platform single sign-on I created a script that checks the user’s password expiration date so that we can alert the user that their password is expiring within 14 days. I want the script to run once a day. I created a launch daemon to run the script. The script and the launch daemon get installed on every Mac with PSSO setup. If the user’s password is expiring on a date that is more than 14 days away the script slimply logs the expiration date and how many days are remaining. The problem I have run into is that if the Mac is not currently connected to the internet when the launch daemon runs the script, there will be no results from the password expiration check with Microsoft. How can I get the launch daemon to run the script again? Currently I have the launch daemon configured to run at a specific hour and minute daily. The deployment script that writtes the password expiration check script and the lauch daemon takes note of the current hour and minute and uses those values to set when the launch daemon will run. Previously I had it set to run once every 86,400 seconds. With either setting, I run into the same issue. Most of the time everything works.
If you add a check for internet and have the script exit non zero when there is no internet connection.
You could add this to your launch daemon:
<key>KeepAlive</key>
<dict> <key>SuccessfulExit</key>
<false/>
</dict>
This will have launchd rerun the job again until it has a successful exit.
Not sure if it is still supported but you may also want to add a ThrottleInterval key to the daemon to slow down the retries.
Hope that helps
Thanks! I will try this. Someone suggested that I add in a check for an active Global Protect connection. Without it any Mac outside the corporate network will fail to reach the server that is responsible for for checking the password age.
If you add a check for internet and have the script exit non zero when there is no internet connection.
You could add this to your launch daemon:
<key>KeepAlive</key> <dict> <key>SuccessfulExit</key> <false/> </dict>
This will have launchd rerun the job again until it has a successful exit.
Not sure if it is still supported but you may also want to add a ThrottleInterval key to the daemon to slow down the retries.
Hope that helps
When I added in the things you mentioned my launch daemon failed to load. Here’s what is in the current (working) launch daemon. Maybe I did not add the additional keys properly.
<?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.eleven9.password.status</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>-c</string>
<string>/Library/Scripts/Password_Status_Alert.sh</string>
</array>
<key>StandardOutPath</key>
<string>/var/log/PasswordStatusLaunchD.log</string>
<key>StandardErrorPath</key>
<string>/var/log/PasswordStatusError.log</string>
<key>RunAtLoad</key>
<true/>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>${minute}</integer>
<key>Hour</key>
<integer>${hour}</integer>
</dict>
<key>UserName</key>
<string>root</string>
</dict>
</plist>
In your example LaunchDaemon are you actually writing “${minute}” and “${hour}” into the .plist for the LaunchDaemon. That might cause the daemon to not load.
You don’t need the “UserName” key to specify “root” as LaunchDaemon’s default to running as root.
I’d agree with
In your example LaunchDaemon are you actually writing “${minute}” and “${hour}” into the .plist for the LaunchDaemon. That might cause the daemon to not load.
You don’t need the “UserName” key to specify “root” as LaunchDaemon’s default to running as root.
I’d agree with
Thanks for the help! The script that deploys the launch daemon is writing the correct values to the launch daemon PLIST. When I added the SuccessfulExit key I got errors trying to load the launch daemon. When I have time later today I will try again.
Here is the launch daemon with user trimmed out as
<?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.eleven9.password.status</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>-c</string>
<string>/Library/Scripts/Password_Status_Alert.sh</string>
</array>
<key>StandardOutPath</key>
<string>/var/log/PasswordStatusLaunchD.log</string>
<key>StandardErrorPath</key>
<string>/var/log/PasswordStatusError.log</string>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>86400</integer>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<true/>
</dict>
</dict>
</plist>I would also keep in mind that daemon’s run at boot, not at user login so your script may not run as intended if the user is at the login screen.
I have a GP detection script if you need some help in that area.
Here is the launch daemon with user trimmed out as
<?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.eleven9.password.status</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>-c</string>
<string>/Library/Scripts/Password_Status_Alert.sh</string>
</array>
<key>StandardOutPath</key>
<string>/var/log/PasswordStatusLaunchD.log</string>
<key>StandardErrorPath</key>
<string>/var/log/PasswordStatusError.log</string>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>86400</integer>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<true/>
</dict>
</dict>
</plist> I would also keep in mind that daemon’s run at boot, not at user login so your script may not run as intended if the user is at the login screen.
I have a GP detection script if you need some help in that area.
Thanks! I will work on this later today. I have an appointment I need to get to. Earlier this year, I created a script that detects Global Protect connections. This is how I identify Macs that are checking in and sending inventories but are not in actual use. They’re likely in a sleep state. I would be interested in seeing what you wrote. It might be better than mine. I will be adding a function that checks if GP is active before it runs the password expiration check. I appreciate the help.
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.
