Posted on 10-28-2024 08:57 AM
I have a large number of labs in our district and students will either walk away from their workstations at the end of class and rely on another student switch users or just lock their account and leave. Both scenarios leave the student logged in. This can create some issues when attempting to use remote commands so I am looking for a configuration or script that I can deploy that will log users out. I would think the easiest way to do this is deploy something at the end of the day. Just wondering if anyone has something they are using that they like.
Solved! Go to Solution.
Posted on 10-29-2024 07:40 AM
I run a pair of scripts, they are launched by a pair of Launch Daemons.
One will attempt to force log out any user account on the Mac at a set time, thus allowing my power management settings to shut the Mac down. But this can hit problems when the user leaves unsaved work open.
The second is a bit more draconian. It will shut the Mac down at a set time, regardless of work saved or not.
These are the bits of the script that do the work, I have logging in place so I can check on things later if i need to.
Logout script does this...
CURRUSER=$(/usr/bin/who | /usr/bin/grep console | /usr/bin/head -n 1 | /usr/bin/awk '{print $1}')
# Kill the login session
/bin/kill `ps uaxww | grep $CURRUSER | grep loginwindow | awk '{print $2}'`
The Hard Shutdown script has this added to it after the kill...
shutdown -h now
The LaunchDaemon for the first script is...
<?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.UNIQUE.NAME.FOR.DAEMON</string>
<key>ProgramArguments</key>
<array>
<string>/Path/to/script/shutdown.sh</string>
<string>-argument</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>20</integer>
<key>Minute</key>
<integer>55</integer>
</dict>
</dict>
</plist>
And the Hard ShutdownDaemon is...
<?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.UNIQUE.NAME.FOR.DAEMON</string>
<key>ProgramArguments</key>
<array>
<string>/PATH/TO/SCRIPT/shutdownhard.sh</string>
<string>-argument</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>21</integer>
<key>Minute</key>
<integer>15</integer>
</dict>
</dict>
</plist>
You will need to put in a Unique name for the LaunchDaemons, and the correct Path to your scripts. You will also note I have the Logout run at 20:30 daily and the Hard shutdown at 21:15, My power settings are set to shutdown at 21:00 daily.
As these are LaunchDaemons they are set to run at every boot, and the Power management settings are used for the most part to shut the Macs down in a nice way.
In addition I do have a loginwindow profile that includes the Log out after 30 mins of inactivity, but this does not always work because they can leave unsaved work open.
As with all scripts, please test, test and test again before putting into production.
Posted on 10-28-2024 11:07 AM
If you're using something Jamf Connect, you can set this up. That's probably the easiest way.
Posted on 10-28-2024 11:38 AM
@mattjerome Is there a list of configurations for a plist upload somewhere? I am assuming that would be how to accomplish that using Jamf Connect.
Posted on 10-28-2024 11:48 AM
This doc has all the info you'd need https://learn.jamf.com/en-US/bundle/jamf-connect-documentation-current/page/Jamf_Connect_App_for_mac...
Posted on 10-28-2024 11:55 AM
You can use a login window configuration profile.
Posted on 10-28-2024 06:42 PM
In addition to the login window payload to log users out after XYZ inactivity, I recommend a daily reboot also.
Posted on 10-29-2024 06:07 AM
Yeah, I have that in place now but with mixed results. If I have a lab of 40 workstations, I can get about 2/3 of them to restart properly. Hence the need to see if logged in users is one of the reasons for this.
Posted on 10-29-2024 07:40 AM
I run a pair of scripts, they are launched by a pair of Launch Daemons.
One will attempt to force log out any user account on the Mac at a set time, thus allowing my power management settings to shut the Mac down. But this can hit problems when the user leaves unsaved work open.
The second is a bit more draconian. It will shut the Mac down at a set time, regardless of work saved or not.
These are the bits of the script that do the work, I have logging in place so I can check on things later if i need to.
Logout script does this...
CURRUSER=$(/usr/bin/who | /usr/bin/grep console | /usr/bin/head -n 1 | /usr/bin/awk '{print $1}')
# Kill the login session
/bin/kill `ps uaxww | grep $CURRUSER | grep loginwindow | awk '{print $2}'`
The Hard Shutdown script has this added to it after the kill...
shutdown -h now
The LaunchDaemon for the first script is...
<?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.UNIQUE.NAME.FOR.DAEMON</string>
<key>ProgramArguments</key>
<array>
<string>/Path/to/script/shutdown.sh</string>
<string>-argument</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>20</integer>
<key>Minute</key>
<integer>55</integer>
</dict>
</dict>
</plist>
And the Hard ShutdownDaemon is...
<?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.UNIQUE.NAME.FOR.DAEMON</string>
<key>ProgramArguments</key>
<array>
<string>/PATH/TO/SCRIPT/shutdownhard.sh</string>
<string>-argument</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>21</integer>
<key>Minute</key>
<integer>15</integer>
</dict>
</dict>
</plist>
You will need to put in a Unique name for the LaunchDaemons, and the correct Path to your scripts. You will also note I have the Logout run at 20:30 daily and the Hard shutdown at 21:15, My power settings are set to shutdown at 21:00 daily.
As these are LaunchDaemons they are set to run at every boot, and the Power management settings are used for the most part to shut the Macs down in a nice way.
In addition I do have a loginwindow profile that includes the Log out after 30 mins of inactivity, but this does not always work because they can leave unsaved work open.
As with all scripts, please test, test and test again before putting into production.
Posted on 10-31-2024 07:37 AM
Thank you for the information. I am still learning how to use Daemons so I will play with this and see if I can get it to work properly.
Posted on 10-31-2024 08:12 AM
LaunchDaemons run at boot. If they run a script it will be done as the root user. They can't interact with the GUI, because chances are when they run there is no user logged in.
LaunchAgents run at Login, if they run a script it will be done as the logging in user. These can interact with the GUI, because there is a user logging in.
They are both fussy about the permissions for themselves and for scripts they run.
LaunchAgents permissions should be 644 and any script they run should be 755
LaunchDaemons permissions should be 644 and any script they run should be 700
With both you need a unique name for the process, that goes in the plist.
Posted on 11-01-2024 09:09 AM
Looking at the script for logging out the user, doesn't
CURRUSER
only going to grab the current user still logged in? What if there are multiple users that have not properly logged out of the workstation. This is a student lab environment so there is a really good chance that two or three students may be logged into a workstation.
Posted on 11-01-2024 09:32 AM
We dont have Fast user switching on, so we only have one user logged in at a time. Sorry, I have never looked into that situation. The hard shutdown will still work.
You can try switching to the users command rather than the who one. I dont have a mac to test it on with multiple accounts logged in, but the users command is supposed to show all logged in users.
I would then use a for loop to run through each one at a time.
CURRUSER=$(users)
for eachuser in $CURRUSER
do
# Kill the login session
/bin/kill `ps uaxww | grep $eachuser | grep loginwindow | awk '{print $2}'`
done
I have not tested that script, I just wrote it on the fly, so please test it out first,
Posted on 11-01-2024 10:46 AM
Okay, that makes sense. I took your script and worked it a bit more.
# List all logged-in users and exclude "root" and "console" users
loggedInUsers=$(who | awk '{print $1}' | sort | uniq | grep -v -e '^root$' -e '^console$')
# Loop through each user and log them out
for user in $loggedInUsers; do
echo "Logging out user: $user"
pkill -KILL -u "$user"
done
echo "All users have been logged out."
# Reboot the system
shutdown -r now
I added a reboot at the end just for good measure. I have tested a couple of time with a policy and it seems to work. I even tested with a user logged in and an unsaved word document and it logged out both accounts and rebooted the workstation.