Posted on 08-16-2017 06:31 PM
Just putting this here for feedback, and for people to use if needed
We have about 1600 student macs in use, and there are a few kids who will play games in class/message friends/get distracted basically. Sometimes, a configuration profiles is okay, the parents are on board with the restrictions, but we wanted to have restrictions only apply during the school blocks.
The basic logic for this is
1. Check the time every 5 minutes
2. If it's during class time, check to see if the restrictions are applied
3. If they are? Do nothing. If not? Install them
4. If it's outside class time (this includes weekends and school holidays). check to see if the restrictions have been removed
5. They have? Do nothing. They haven't? Remove them
We need a package to install, and this is what's in the package
- restrictions.sh (see below)
- com.SCHOOL.it.restrictions.plist (see below)
- rs_stdout (log the output)
- disabled.txt (name changes based on enable/disable status, this is how it get's checked)
- com.SCHOOL.it.restrictions.mobileconfig (config profile downloaded from JSS to be installed)
install.sh (stored in JSS, ran after the package above has installed):
#!/bin/sh
##Change Directory to the restrictions one added by the package
cd /Applications/SCHOOL/restrictions
##RESTRICTION SCRIPT
##Make management.sh and restrictions.sh executable
sudo chmod a+x restrictions.sh
##PLIST
##Check if /Library/LaunchDaemons exists
##If not, then create it
if [ ! -d "/Library/LaunchDaemons" ]; then
sudo mkdir "/Library/LaunchDaemons"
fi
##Copy plists into it
sudo cp com.SCHOOL.it.restrictions.plist /Library/LaunchDaemons/
##make plists read/writeable (644)
sudo chmod 644 /Library/LaunchDaemons/com.SCHOOL.it.restrictions.plist
##change ownership (chown) of plists to root user and wheel group
sudo chown root:wheel /Library/LaunchDaemons/com.SCHOOL.it.restrictions.plist
##load the plists into current launchd tasks
##Not doing this will mean the computer has to be restarted to load the plists
sudo launchctl load -w /Library/LaunchDaemons/com.SCHOOL.it.restrictions.plist
com.SCHOOL.it.restrictions.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>GroupName</key>
<string>wheel</string>
<key>InitGroups</key>
<true/>
<key>Label</key>
<string>com.SCHOOL.it.restrictions</string>
<key>Program</key>
<string>/Applications/SCHOOL/restrictions/restrictions.sh</string>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/com.SCHOOL.it.resrictions.err</string>
<key>StandardOutPath</key>
<string>/Applications/SCHOL/restrictions/rs_stdout</string>
<key>StartInterval</key>
<integer>300</integer>
<key>UserName</key>
<string>root</string>
<key>WorkingDirectory</key>
<string>/Applications/SCHOOL/restrictions</string>
</dict>
</plist>
restrictions.sh:
#!/bin/sh
## Check if its holidays
is_holidays() {
##Get the current date as a big old number YYYYMMDD
current=$( date +"%Y%m%d")
##Will be set to true if it is the holidays
HOLIDAYS=false
##Example for term 2 break in 2017
#Start day is July 1 2017, so in YYYMMDD thats 20170701
#End day is July 16 2017, so in YYYMMDD thats 20170716
##Term 2 Break 2017 20170701 - 20170116
if [[ "$current" -ge 20170701 && "$current" -le 20170716 ]] ; then
##Echo the holiday period out to the log file, for debugging
echo "Winter Holidays 2017"
HOLIDAYS=true
fi
## Check if its a public holiday
#Example for racing cup 2017
#On November 1 2017
##In YYYMMDD thats 20171101
## -eq is the equality check
#Racing Cup - 20171101
if [[ "$current" -eq 20171101 ]] ; then
echo "Racing Cup 2017"
HOLIDAYS = true
}
## Check if its during the school day
is_school(){
## Get the hour and minute as one string in 24 hour time
dateHour=$( date +"%H%M")
current=$( date +"%Y-%m-%d %H:%M")
#remove leading zero so it isnt processed as an octal
dateHour=$(expr $dateHour + 0)
dayOfWeek=$(date +%u)
SCHOOL=false
#If it isnt a day off, then check if it's during school time
if ! $HOLIDAYS ; then
echo "SCHOOL TERM"
#This compares the HHMM number (no colon) to the numbers for start and end times of a block
#If between times for block 1, 2, or 3, then school is true, otherwise it's false
#Check monday to friday
if [[ "$dayOfWeek" -le 5 ]] ; then
##Check if we're during blocks 1, 2, 3, recess, lunch
##Example of block 1
## Block 1
## between 09:05 and 10:41
if [[ "$dateHour" -ge 905 && "$dateHour" -le 1041 ]] ; then
##Echo out the time period for debugging if needed
echo "Block 1"
##Set school to true, as we are in school time
SCHOOL=true
fi
fi
fi
}
## Check to see if the log is over 2mb
check_log(){
##Check to see how big the log file is
##If more than 2mb then remove
logfile=rs_stdout
actualsize=$(wc -c <"$logfile")
maxSize=2000000
echo "Log size is $actualsize bytes"
if [[ $actualsize -ge $maxSize ]]; then
echo "Log is 2mb or greater. Removing..."
sudo rm rs_stdout
sudo touch rs_stdout
echo "Log Removed."
fi
}
## Core script. Check if we're in school times (enable) or not (disable)
main(){
echo "$current"
if $SCHOOL ; then
echo "Enable_RS"
if [ -f disabled.txt ]; then
echo "Currently Disabled..."
echo "Enabling..."
##-I is install
##-F is telling it that its from a file
##This installs the restriction profiles
sudo /usr/bin/profiles -I -F com.SCHOOL.it.restrictions.mobileconfig
##Change name of enabled/disabled.txt
sudo mv disabled.txt enabled.txt
echo "Enabled"
else
echo "Already enabled"
fi
else
echo "Disable_RS"
if [ -f enabled.txt ]; then
echo "Currently Enabled..."
echo "Disabling..."
##-R is Remove
##-F is telling it that its from a file
##This removes the restriction profile
sudo /usr/bin/profiles -R -F com.SCHOOL.it.restrictions.mobileconfig
##Change name of enabled/disabled.txt
sudo mv enabled.txt disabled.txt
echo "Disabled"
else
echo "Already Disabled"
fi
fi
##This just breaks up the log file into more readable sections
echo "+----------------+
"
}
##Call all the functions
is_holidays
is_school
check_log
main
A few notes about all this:
I know it's possibly simpler to open the JSS up to external networks, and have it check in every so often to download a profile, but we don't want students without internet having them put on unfairly, or have them able to be removed if the JSS isn't available (turn wifi off)
Most of this was pieced together from about a dozen articles, mainly the plist and launchd aspects. I spent ages messing around with getting the plist to load correctly, handy app called LaunchControl was really helpful with setting everything up and finding problems. If there's any non-standard approach to the permissions or users, it's definitely not intentional.
The restrictions script is much longer, I've added dates in for school holidays for the next year, as well as known public holidays. I only included one example of each type of holiday here
There's also a check to see if the date is earlier than june 2017 (sometimes the batteries run flat and the time resets. This could be changed to always install restrictions if this happens, but as it happens most often on holidays, I'm staying on the safe side)