Help users easily identify their 50 largest directories in preparation to upgrade to macOS Ventura
Background
One of the most common barriers for general Workforce users upgrading to the next major operating system is lack of available disk space.
We have benefited greatly from Zack Thompson’s Get-LatestOSSupported.sh Jamf Pro Extension Attribute which helps inform users if their Mac meets Apple’s latest requirements.
However, frequently users observe the message: Ventura / Insufficient Storage
.
swiftDialog
Disk Usage with To aid users in determining where all their hard drive space has gone, we have a Jamf Pro Self Service policy which leverages du
and outputs text
files of the top 50 directories of the root volume and the user’s home folder.
The utilitarian results are sorted by size, in gigabytes, and saved to the user’s Desktop.
Additionally, the macOS built-in Storage information is automatically launched so the users can easily review Apple’s recommendations.
Thin Local Time Machine Snapshots
When users have Time Machine enabled, the script also reports the output of:tmutil listlocalsnapshots /
Cautiously following the included instructions tends to be the “quickest win” in freeing up hard drive space for users looking to upgrade now!
Configuration
Complete the following steps to help users identify their 50 largest directories in preparation to upgrade to macOS Ventura.
A. Add the Disk Usage with swiftDialog script to your Jamf Pro server
- Add the
Display Message with swiftDialog
script to your Jamf Pro server - Edit
--infobuttontext
and--infobuttonaction
to the correct information for your organization - Specify the following for Options > Parameter Labels
- Parameter 4:
Script Log Location
- Parameter 5:
Debug Mode [ true (default) | false ]
- Parameter 6:
Expected Duration (in seconds)
- Parameter 4:
- Click Save
Latest version availble on GitHub.
#!/bin/bash #################################################################################################### # # ABOUT # # Disk Usage with swiftDialog # Help users determine what's occupying all their hard drive space # # See: https://snelson.us/2022/11/disk-usage-with-swiftdialog-0-0-2/ # #################################################################################################### # # HISTORY # # Version 0.0.1, 09-Nov-2022, Dan K. Snelson (@dan-snelson) # Original swiftDialog, proof-of-concept version # # Version 0.0.2, 12-Nov-2022, Dan K. Snelson (@dan-snelson) # Removed `--ontop` from Progress dialog (for longer execution times) # Hard-coded estimated execution time for user's home folder to 60 percent # Opened the macOS built-in Storage information # # Version 0.0.3, 14-Nov-2022, # Modifided du's stderr redirection (thanks, @Pico!) # #################################################################################################### #################################################################################################### # # Variables # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Global Variables # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # scriptVersion="0.0.3" export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/ loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' ) loggedInUserHome=$( dscl . read /Users/"${loggedInUser}" NFSHomeDirectory | awk -F ": " '{print $2}' ) machineName=$( scutil --get LocalHostName ) volumeName=$( diskutil info / | grep "Volume Name:" | awk '{print $3,$4}' ) timestamp=$( date '+%Y-%m-%d-%H%M%S' ) diskUsageEntireVolumeTop50=$( mktemp /var/tmp/diskUsageEntireVolumeTop50.XXXX ) diskUsageUsersHomeTop50=$( mktemp /var/tmp/diskUsageUsersHomeTop50.XXXX ) outputFileNameEntireVolume="$loggedInUserHome/Desktop/$machineName-Volume-Usage-$timestamp.txt" outputFileNameUsersHome="$loggedInUserHome/Desktop/$loggedInUser-Home-Usage-$timestamp.txt" osVersion=$( sw_vers -productVersion ) osMajorVersion=$( echo "${osVersion}" | awk -F '.' '{print $1}' ) dialogApp="/usr/local/bin/dialog" dialogWelcomeLog=$( mktemp /var/tmp/dialogWelcomeLog.XXXX ) dialogProgressLog=$( mktemp /var/tmp/dialogProgressLog.XXXX ) dialogCompleteLog=$( mktemp /var/tmp/dialogCompleteLog.XXXX ) scriptLog="${4:-"/var/tmp/org.churchofjesuschrist.log"}" debugMode="${5:-"true"}" estimatedTotalSeconds="${6:-"120"}" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Free Space Variables # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # freeSpace=$( diskutil info / | grep -E 'Free Space|Available Space|Container Free Space' | awk -F ":\s*" '{ print $2 }' | awk -F "(" '{ print $1 }' | xargs ) freeBytes=$( diskutil info / | grep -E 'Free Space|Available Space|Container Free Space' | awk -F "(\\\(| Bytes\\\))" '{ print $2 }' ) diskBytes=$( diskutil info / | grep -E 'Total Space' | awk -F "(\\\(| Bytes\\\))" '{ print $2 }' ) freePercentage=$( echo "scale=2; ( $freeBytes * 100 ) / $diskBytes" | bc ) diskSpace="$freeSpace free ( ${freePercentage}% available )" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Welcome Dialog Title, Message and Icon # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # welcomeTitle="Disk Usage ($scriptVersion)" if [[ ${debugMode} == "true" ]]; then welcomeTitle="DEBUG MODE | $welcomeTitle" fi welcomeMessage="This script analyzes the following locations and outputs text files to your Desktop, which list the 50 largest directories for both: \n- **${volumeName}** (non-system files) \n- **${loggedInUserHome}** \n\nPlease be patient as execution time can be in excess of ${estimatedTotalSeconds} seconds. \n\nClick **Continue** to proceed." welcomeIcon="/System/Library/Extensions/IOStorageFamily.kext/Contents/Resources/Internal.icns" overlayIcon=$( defaults read /Library/Preferences/com.jamfsoftware.jamf.plist self_service_app_path ) button1text="Continue …" button2text="Quit" infobuttontext="KB8675309" infobuttonaction="https://servicenow.company.com/support?id=kb_article_view&sysparm_article=${infobuttontext}" welcomeProgressText="Waiting; click Continue to proceed" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Welcome Dialog Settings and Features # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # dialogWelcome="$dialogApp \ --title \"$welcomeTitle\" \ --message \"$welcomeMessage\" \ --icon \"$welcomeIcon\" \ --overlayicon \"$overlayIcon\" \ --button1text \"$button1text\" \ --button2text \"$button2text\" \ --infobuttontext \"$infobuttontext\" \ --infobuttonaction \"$infobuttonaction\" \ --progress \ --progresstext \"$welcomeProgressText\" \ --moveable \ --ontop \ --titlefont size=22 \ --messagefont size=14 \ --iconsize 135 \ --width 700 \ --height 325 \ --commandfile \"$dialogWelcomeLog\" " # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Progress Dialog Title, Message and Icon # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # progressTitle="Disk Usage ($scriptVersion)" progressMessage="Analyzing ${volumeName} …" progressIcon="/System/Applications/Utilities/Disk Utility.app" progressProgressText="Initializing …" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Progress Dialog Settings and Features # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # dialogProgress="$dialogApp \ --title \"$progressTitle\" \ --message \"$progressMessage\" \ --icon \"$progressIcon\" \ --progress \ --progresstext \"$progressProgressText\" \ --mini \ --moveable \ --commandfile \"$dialogProgressLog\" " # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Complete Dialog Title, Message and Icon # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # completeTitle="Disk Usage ($scriptVersion)" if [[ ${debugMode} == "true" ]]; then completeTitle="DEBUG MODE | $completeTitle" fi completeMessage="### Analysis complete \n\nPlease review the following files, which have been saved to your Desktop: \n- **$machineName-Volume-Usage-$timestamp.txt** \n- **$loggedInUser-Home-Usage$timestamp.txt**" completeIcon="/System/Library/Extensions/IOStorageFamily.kext/Contents/Resources/Internal.icns" overlayIcon=$( defaults read /Library/Preferences/com.jamfsoftware.jamf.plist self_service_app_path ) completeButton1text="Close" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Complete Dialog Settings and Features # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # dialogComplete="$dialogApp \ --title \"$completeTitle\" \ --message \"$completeMessage\" \ --icon \"$completeIcon\" \ --overlayicon \"$overlayIcon\" \ --button1text \"$completeButton1text\" \ --infobuttontext \"$infobuttontext\" \ --infobuttonaction \"$infobuttonaction\" \ --moveable \ --ontop \ --titlefont size=22 \ --messagefont size=14 \ --iconsize 135 \ --width 700 \ --height 325 \ --commandfile \"$dialogCompleteLog\" " # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate logged-in user # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ -z "${loggedInUser}" || "${loggedInUser}" == "loginwindow" ]]; then echo "No user logged-in; exiting." exit 0 else uid=$(id -u "${loggedInUser}") fi #################################################################################################### # # Functions # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Script Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function updateScriptLog() { echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # JAMF Display Message (for fallback in case swiftDialog fails to install) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function jamfDisplayMessage() { updateScriptLog "Jamf Display Message: ${1}" /usr/local/jamf/bin/jamf displayMessage -message "${1}" & } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Check for / install swiftDialog (Thanks big bunches, @acodega!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function dialogCheck() { # Get the URL of the latest PKG From the Dialog GitHub repo dialogURL=$(curl --silent --fail "https://api.github.com/repos/bartreardon/swiftDialog/releases/latest" | awk -F '"' "/browser_download_url/ && /pkg\"/ { print \$4; exit }") # Expected Team ID of the downloaded PKG expectedDialogTeamID="PWA5E9TQ59" # Check for Dialog and install if not found if [ ! -e "/Library/Application Support/Dialog/Dialog.app" ]; then updateScriptLog "Dialog not found. Installing..." # Create temporary working directory workDirectory=$( /usr/bin/basename "$0" ) tempDirectory=$( /usr/bin/mktemp -d "/private/tmp/$workDirectory.XXXXXX" ) # Download the installer package /usr/bin/curl --location --silent "$dialogURL" -o "$tempDirectory/Dialog.pkg" # Verify the download teamID=$(/usr/sbin/spctl -a -vv -t install "$tempDirectory/Dialog.pkg" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()') # Install the package if Team ID validates if [ "$expectedDialogTeamID" = "$teamID" ] || [ "$expectedDialogTeamID" = "" ]; then /usr/sbin/installer -pkg "$tempDirectory/Dialog.pkg" -target / else jamfDisplayMessage "Dialog Team ID verification failed." exit 1 fi # Remove the temporary working directory when done /bin/rm -Rf "$tempDirectory" else updateScriptLog "swiftDialog version $(dialog --version) found; proceeding..." fi } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Run command as logged-in user (thanks, @scriptingosx!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function runAsUser() { # shellcheck disable=SC2145 updateScriptLog "Run \"$@\" as \"$uid\" … " launchctl asuser "$uid" sudo -u "$loggedInUser" "$@" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Quit Script (thanks, @bartreadon!) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function quitScript() { updateScriptLog "Quitting …" updateProgressDialog "quit: " sleep 1 updateScriptLog "Exiting …" # Remove dialogWelcomeLog if [[ -e ${dialogWelcomeLog} ]]; then updateScriptLog "Removing ${dialogWelcomeLog} …" rm "${dialogWelcomeLog}" fi # Remove dialogProgressLog if [[ -e ${dialogProgressLog} ]]; then updateScriptLog "Removing ${dialogProgressLog} …" rm "${dialogProgressLog}" fi # Remove dialogCompleteLog if [[ -e ${dialogCompleteLog} ]]; then updateScriptLog "Removing ${dialogCompleteLog} …" rm "${dialogCompleteLog}" fi # Remove diskUsageEntireVolumeTop50 if [[ -e ${diskUsageEntireVolumeTop50} ]]; then updateScriptLog "Removing ${diskUsageEntireVolumeTop50} …" rm "${diskUsageEntireVolumeTop50}" fi # Remove diskUsageUsersHomeTop50 if [[ -e ${diskUsageUsersHomeTop50} ]]; then updateScriptLog "Removing ${diskUsageUsersHomeTop50} …" rm "${diskUsageUsersHomeTop50}" fi updateScriptLog "Goodbye!" exit "${1}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Update Progress Dialog # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function updateProgressDialog() { sleep 0.35 echo "${1}" >> "${dialogProgressLog}" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Analyze Disk Usage for the entire volume # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function analyzeDiskUsageEntireVolume() { updateScriptLog "Output disk usage statistics of \"${volumeName}\" to: ${diskUsageEntireVolumeTop50}" du -I System -axrg / 2>/dev/null | sort -nr | head -n 50 >> "$diskUsageEntireVolumeTop50" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Analyze Disk Usage for the user's home folder # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function analyzeDiskUsageUsersHome() { updateScriptLog "Output disk usage statistics of \"$loggedInUserHome\" to: ${diskUsageUsersHomeTop50}" du -axrg "$loggedInUserHome" 2>/dev/null | sort -nr | head -n 50 >> "$diskUsageUsersHomeTop50" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Open Storage Information # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function openStorageInformation() { if [[ "${osMajorVersion}" -ge 13 ]] ; then runAsUser open x-apple.systempreferences:com.apple.settings.Storage else runAsUser open /System/Library/CoreServices/Applications/Storage\ Management.app fi } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Output Results for the entire volume # shellcheck disable=SC2129 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function outputResultsEntireVolume() { updateScriptLog "Disk usage for volume \"$volumeName\" on computer \"$machineName\" " updateScriptLog "Report Location: $outputFileNameEntireVolume" echo "--------------------------------------------------------------------------------------------------" > "$outputFileNameEntireVolume" echo "Disk usage for volume \"$volumeName\" on computer \"$machineName\" " >> "$outputFileNameEntireVolume" echo "Disk Space: $diskSpace" >> "$outputFileNameEntireVolume" echo "Report Location: $outputFileNameEntireVolume" >> "$outputFileNameEntireVolume" echo "--------------------------------------------------------------------------------------------------" >> "$outputFileNameEntireVolume" echo " " >> "$outputFileNameEntireVolume" echo " " >> "$outputFileNameEntireVolume" echo " " >> "$outputFileNameEntireVolume" echo "GBs Directory or File" >> "$outputFileNameEntireVolume" echo " " >> "$outputFileNameEntireVolume" cat "${diskUsageEntireVolumeTop50}" >> "$outputFileNameEntireVolume" echo " " >> "$outputFileNameEntireVolume" echo "--------------------------------------------------------------------------------------------------" >> "$outputFileNameEntireVolume" } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Output Results or the user's home folder # shellcheck disable=SC2129 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function outputResultsUsersHome() { updateScriptLog "Disk usage for \"$loggedInUserHome\" for volume \"$volumeName\" on computer \"$machineName\" " updateScriptLog "Report Location: $outputFileNameUsersHome" echo "--------------------------------------------------------------------------------------------------" > "$outputFileNameUsersHome" echo "Disk usage for \"$loggedInUserHome\" for volume \"$volumeName\" on computer \"$machineName\" " >> "$outputFileNameUsersHome" echo "Disk Space: $diskSpace" >> "$outputFileNameUsersHome" echo "Report Location: $outputFileNameUsersHome" >> "$outputFileNameUsersHome" echo "--------------------------------------------------------------------------------------------------" >> "$outputFileNameUsersHome" echo " " >> "$outputFileNameUsersHome" echo " " >> "$outputFileNameUsersHome" echo " " >> "$outputFileNameUsersHome" echo "GBs Directory or File" >> "$outputFileNameUsersHome" echo " " >> "$outputFileNameUsersHome" cat "${diskUsageUsersHomeTop50}" >> "$outputFileNameUsersHome" echo " " >> "$outputFileNameUsersHome" echo "--------------------------------------------------------------------------------------------------" >> "$outputFileNameUsersHome" echo " ### # Time Machine Information ### " >> "$outputFileNameUsersHome" tmDestinationInfo=$( tmutil destinationinfo ) if [[ "${tmDestinationInfo}" == *"No destinations configured"* ]]; then echo "WARNING: Time Machine destination NOT configured." >> "$outputFileNameUsersHome" else tmutil listlocalsnapshots / >> "$outputFileNameUsersHome" echo " --- - Thin Local Time Machine Snapshots --- Thinning local Time Machine snapshots can quickly free up disk space by PERMANENTLY deleting local Time Machine snapshots. man tmutil thinlocalsnapshots mount_point [purge_amount] [urgency] Thin local Time Machine snapshots for the specified volume. When purge_amount and urgency are specified, tmutil will attempt (with urgency level 1-4) to reclaim purge_amount in bytes by thinning snapshots. If urgency is not specified, the default urgency will be used. ABSOLUTELY UNSUPPORTED EXAMPLES TO BE USED AT YOUR OWN RISK: # Free 20 GB of snapshots stored on the boot drive (with maximum urgency) tmutil thinlocalsnapshots / 21474836480 4 # Free 36 GB of snapshots stored on the boot drive (with maximum urgency) tmutil thinlocalsnapshots / 38654705664 4" >> "$outputFileNameUsersHome" fi } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Analyze Disk Usage with Progress # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # function analyzeDiskUsageWithProgress() { updateScriptLog "Disk Space: $diskSpace" updateScriptLog "Analyze Disk Usage with Progress (1 of 2)" eval "$dialogProgress" & sleep 0.35 if [[ ${debugMode} == "true" ]]; then updateProgressDialog "title: DEBUG MODE | $progressTitle" updateProgressDialog "message: DEBUG MODE. Please wait for 10 seconds …" sleep 2 updateProgressDialog "progresstext: Processing …" sleep 2 updateProgressDialog "progresstext: Analyzing …" sleep 2 updateProgressDialog "progresstext: Thinking …" sleep 2 updateProgressDialog "progresstext: Almost done …" sleep 2 updateProgressDialog "quit: " else ### # Analyze Disk Usage for entire volume ### updateScriptLog "Analyze Disk Usage for \"${volumeName}\"" updateProgressDialog "message: Analyze Disk Usage for \"${volumeName}\"" updateProgressDialog "progress: 0" updateProgressDialog "progresstext: Initializing …" SECONDS="0" analyzeDiskUsageEntireVolume & updateProgressDialog "progresstext: Analyzing …" while [[ -n $(pgrep -x "du|sort|head") ]]; do progressPercentage=$( echo "scale=2 ; ( $SECONDS / $estimatedTotalSeconds ) * 100" | bc | sed 's/\.00$//') updateProgressDialog "progress: ${progressPercentage}" updateProgressDialog "progresstext: Analyzing: ${progressPercentage}%" done updateProgressDialog "progress: 100" updateProgressDialog "progresstext: Elapsed Time: $(printf '%dh:%dm:%ds\n' $((SECONDS/3600)) $((SECONDS%3600/60)) $((SECONDS%60)))" updateScriptLog "Elapsed Time for \"${volumeName}\": $(printf '%dh:%dm:%ds\n' $((SECONDS/3600)) $((SECONDS%3600/60)) $((SECONDS%60)))" outputResultsEntireVolume ### # Analyze Disk Usage for user's home directory ### updateScriptLog "Analyze Disk Usage with Progress (2 of 2)" updateScriptLog "Analyze Disk Usage for \"${loggedInUserHome}\"" updateProgressDialog "message: Analyze Disk Usage for \"${loggedInUserHome}\"" updateProgressDialog "progress: 0" updateProgressDialog "progresstext: Initializing …" SECONDS="0" estimatedTotalSecondsUsersHome=$( echo "scale=2 ; ( $estimatedTotalSeconds * 0.6 )" | bc ) analyzeDiskUsageUsersHome & updateProgressDialog "progresstext: Analyzing …" while [[ -n $(pgrep -x "du|sort|head") ]]; do progressPercentage=$( echo "scale=2 ; ( $SECONDS / $estimatedTotalSecondsUsersHome ) * 100" | bc | sed 's/\.00$//') updateProgressDialog "progress: ${progressPercentage}" updateProgressDialog "progresstext: Analyzing: ${progressPercentage}%" done updateProgressDialog "progress: 100" updateProgressDialog "progresstext: Elapsed Time: $(printf '%dh:%dm:%ds\n' $((SECONDS/3600)) $((SECONDS%3600/60)) $((SECONDS%60)))" updateScriptLog "Elapsed Time for \"${loggedInUserHome}\": $(printf '%dh:%dm:%ds\n' $((SECONDS/3600)) $((SECONDS%3600/60)) $((SECONDS%60)))" outputResultsUsersHome updateProgressDialog "quit: " fi } #################################################################################################### # # Pre-flight Checks # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Confirm script is running as root # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ $(id -u) -ne 0 ]]; then echo "This script must be run as root; exiting." exit 1 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Client-side Logging # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ! -f "${scriptLog}" ]]; then touch "${scriptLog}" updateScriptLog "*** Created log file via script ***" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Logging preamble # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ ${debugMode} == "true" ]]; then updateScriptLog "\n\n###\n# DEBUG MODE | Disk Usage (${scriptVersion})\n###\n" else updateScriptLog "\n\n###\n# Disk Usage (${scriptVersion})\n###\n" fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate Operating System # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if [[ "${osMajorVersion}" -ge 11 ]] ; then echo "macOS ${osMajorVersion} installed; proceeding ..." else echo "macOS ${osMajorVersion} installed; exiting" jamfDisplayMessage "macOS ${osMajorVersion} installed. Please use the previous version of this script. Exiting." exit 1 fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Validate swiftDialog is installed # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # dialogCheck #################################################################################################### # # Program # #################################################################################################### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Create Welcome Dialog # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "Create Welcome Dialog …" eval "$dialogWelcome" welcomeReturncode=$? case ${welcomeReturncode} in 0) ## Process exit code 0 scenario here updateScriptLog "${loggedInUser} clicked ${button1text};" analyzeDiskUsageWithProgress eval "$dialogComplete" # shellcheck disable=SC2086 if [[ -f "${outputFileNameEntireVolume}" || "${outputFileNameUsersHome}" ]]; then runAsUser open $outputFileNameEntireVolume runAsUser open $outputFileNameUsersHome openStorageInformation quitScript "0" else updateScriptLog "Something went sideways; couldn't find ${outputFileNameEntireVolume} or ${outputFileNameUsersHome}" quitScript "1" fi ;; 2) ## Process exit code 2 scenario here updateScriptLog "${loggedInUser} clicked ${button2text};" quitScript "0" ;; 3) ## Process exit code 3 scenario here updateScriptLog "${loggedInUser} clicked ${infobuttontext};" ;; 4) ## Process exit code 4 scenario here updateScriptLog "${loggedInUser} allowed timer to expire;" quitScript "1" ;; *) ## Catch all processing updateScriptLog "Something else happened; Exit code: ${welcomeReturncode};" quitScript "1" ;; esac # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Exit # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # updateScriptLog "End-of-line." quitScript "0"
B. Create a Jamf Pro Policy to display Disk Usage
- Create a new Jamf Pro Policy, using the following as a guide for Options > General:
- Set Display Name to
Disk Usage with swiftDialog (0.0.2)
- Set Execution Frequency to
Ongoing
- Set Display Name to
- Select the Scripts payload and add the
Disk Usage with swiftDialog (0.0.2)
script, specifying the following Parameter Values- Script Log Location:
/var/log/com.company.log
- Debug Mode [ true (default) | false ]:
true
(change tofalse
when your testing is complete) - Expected Duration (in seconds):
120
- Script Log Location:
- Adjust Scope to your liking; we use our custom All Jamf Pro Compliant Computers Smart Computer Group
- Use the following for Self Service
- Self Service Display Name:
Disk Usage (0.0.2)
- Button Name Before Initiation:
Analyze
- Button Name After Initiation:
Reanalyze
- Description:
- Self Service Display Name:
Please see [KB8675309](https://servicenow.company.com/support?id=kb_article_view&sysparm_article=KB8675309) for a detailed usage instructions. This script analyzes the following locations and outputs text files to your Desktop, which list the 50 largest directories for both: - **Macintosh HD** (non-system files) - **Your User Home Folder** Please be patient as execution time can be in excess of several minutes. Click **Continue** to proceed.
- Click Save
Testing
Expected Duration
Ask a few of your opt-in Beta Tester power-users to execute the policy, then review the policy logs, searching for the phrase Elapsed Time
immediately followed by the duration:
2022-11-12 08:45:42 - Elapsed Time for "Macintosh HD": 0h:0m:42s
In early testing, when the Expected Duration
value was too low, we observed some entertaining percentages:
Unexpected Output
We occasionally observe — and continue to investigate — odd-ball entries from du
‘s output:
GBs Directory or File 75 / 55lhzllqrr540000gq/C/net.telestream.screenflow10 40 /Users/dan 40 /Users 25 /Users/dan/Downloads 24 /Applications 14 /Users/dan/Downloads/UniversalMac_12.6.1_21G217_Restore.ipsw 14 /Users/dan/.tart/vms/13.0.1_22A400-base/disk.img 14 /Users/dan/.tart/vms/13.0.1_22A400-base 14 /Users/dan/.tart/vms 14 /Users/dan/.tart 12 /Users/dan/Downloads/UniversalMac_13.0.1_22A400_Restore.ipsw 6csfxvn_n00000z000007r/C/com.apple.SetupAssistant/com.apple.metal 6csfxvn_n0000000000000/C/com.apple.metalfe 6 /private 6 /Library 5 /Applications/Adobe Photoshop 2023/Adobe Photoshop 2023.app/Contents
Queue the Eagles, because currently I can’t tell you why …
Updates
0.0.3
(14-Nov-2022)
- Modified
du
‘sstderr
redirection (thanks, @Pico!)