Skip to main content

This is an ever growing / changing library of common functions that I have created over the years.  Fairly easy to use, just grab the common functions you need when creating your own scripts.  Thought I would share with the community.  Any feedback is welcome.

 

#!/bin/zsh ###################################################################################################### # # Gobal "Common" variables (do not change these!) # ###################################################################################################### export PATH=/usr/bin:/bin:/usr/sbin:/sbin LOGGED_IN_USER=$( scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }' ) USER_DIR=$( dscl . -read /Users/${LOGGED_IN_USER} NFSHomeDirectory | awk '{ print $2 }' ) OS_PLATFORM=$(/usr/bin/uname -p) [[ "$OS_PLATFORM" == 'i386' ]] && HWtype="SPHardwareDataType.0.cpu_type" || HWtype="SPHardwareDataType.0.chip_type" SYSTEM_PROFILER_BLOB=$( /usr/sbin/system_profiler -json 'SPHardwareDataType') MAC_SERIAL_NUMBER=$( echo $SYSTEM_PROFILER_BLOB | /usr/bin/plutil -extract 'SPHardwareDataType.0.serial_number' 'raw' -) MAC_CPU=$( echo $SYSTEM_PROFILER_BLOB | /usr/bin/plutil -extract "${HWtype}" 'raw' -) MAC_HADWARE_CLASS=$( echo $SYSTEM_PROFILER_BLOB | /usr/bin/plutil -extract 'SPHardwareDataType.0.machine_name' 'raw' -) MAC_RAM=$( echo $SYSTEM_PROFILER_BLOB | /usr/bin/plutil -extract 'SPHardwareDataType.0.physical_memory' 'raw' -) FREE_DISK_SPACE=$(($( /usr/sbin/diskutil info / | /usr/bin/grep "Free Space" | /usr/bin/awk '{print $6}' | /usr/bin/cut -c 2- ) / 1024 / 1024 / 1024 )) MACOS_VERSION=$( sw_vers -productVersion | xargs) SW_DIALOG="/usr/local/bin/dialog" ################################################### # # App Specfic variables (Feel free to change these) # ################################################### SUPPORT_DIR="/Library/Application Support/GiantEagle" OVERLAY_ICON="${SUPPORT_DIR}/SupportFiles/DiskSpace.png" SD_BANNER_IMAGE="${SUPPORT_DIR}/SupportFiles/GE_SD_BannerImage.png" LOG_DIR="${SUPPORT_DIR}/logs" LOG_FILE="${LOG_DIR}/AppDelete.log" LOG_STAMP=$(echo $(/bin/date +%Y%m%d)) ICON_FILES="/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/" JSONOptions=$(mktemp /var/tmp/ClearBrowserCache.XXXXX) BANNER_TEXT_PADDING=" " #Five space to accommodate our logo on the left side SD_INFO_BOX_MSG="" SD_WINDOW_TITLE="${BANNER_TEXT_PADDING}Disk Space Notification" # Swift Dialog version requirements [[ -e "/usr/local/bin/dialog" ]] && SD_VERSION=$( ${SW_DIALOG} --version) || SD_VERSION="0.0.0" MIN_SD_REQUIRED_VERSION="2.3.3" DIALOG_INSTALL_POLICY="install_SwiftDialog" SHOW_DISK_USAGE="ShowDiskUsage" #################################################################################################### # # Functions # #################################################################################################### function create_log_directory () { # Ensure that the log directory and the log files exist. If they # do not then create them and set the permissions. # # RETURN: None # If the log directory doesnt exist - create it and set the permissions if [[ ! -d "${LOG_DIR}" ]]; then /bin/mkdir -p "${LOG_DIR}" /bin/chmod 755 "${LOG_DIR}" fi # If the log file does not exist - create it and set the permissions if [[ ! -f "${LOG_FILE}" ]]; then /usr/bin/touch "${LOG_FILE}" /bin/chmod 644 "${LOG_FILE}" fi } function logMe () { # Basic two pronged logging function that will log like this: # # 20231204 12:00:00: Some message here # # This function logs both to STDOUT/STDERR and a file # The log file is set by the $LOG_FILE variable. # # RETURN: None echo "${1}" 1>&2 echo "$(/bin/date '+%Y%m%d %H:%M:%S'): ${1}\\n" >> "${LOG_FILE}" } function check_swift_dialog_install () { # Check to make sure that Swift Dialog is installed and functioning correctly # Will install process if missing or corrupted # # RETURN: None logMe "Ensuring that swiftDialog version is installed..." if [[ ! -x "${SW_DIALOG}" ]]; then logMe "Swift Dialog is missing or corrupted - Installing from JAMF" install_swift_dialog SD_VERSION=$( ${SW_DIALOG} --version) fi if ! is-at-least "${MIN_SD_REQUIRED_VERSION}" "${SD_VERSION}"; then logMe "Swift Dialog is outdated - Installing version '${MIN_SD_REQUIRED_VERSION}' from JAMF..." install_swift_dialog else logMe "Swift Dialog is currently running: ${SD_VERSION}" fi } function install_swift_dialog () { # Install Swift dialog From JAMF # PARMS Expected: DIALOG_INSTALL_POLICY - policy trigger from JAMF # # RETURN: None /usr/local/bin/jamf policy -trigger ${DIALOG_INSTALL_POLICY} } function welcomemsg () { } autoload 'is-at-least' check_swift_dialog_install create_infobox_message welcomemsg exit 0 function update_display_list () { # setopt -s nocasematch # This function updates the Swift Dialog list display with easy to implement parameter passing... # The Swift Dialog native structure is very strict with the command structure...this routine makes # it easier to implement # # Param list # # $1 - Action to be done ("Create", "Add", "Change", "Clear", "Info", "Show", "Done", "Update") # ${2} - Affected item (2nd field in JSON Blob listitem entry) # ${3} - Icon status "wait, success, fail, error, pending or progress" # ${4} - Status Text # $5 - Progress Text (shown below progress bar) # $6 - Progress amount # increment - increments the progress by one # reset - resets the progress bar to 0 # complete - maxes out the progress bar # If an integer value is sent, this will move the progress bar to that value of steps # the GLOB :l converts any inconing parameter into lowercase case "${1:l}" in "create" | "show" ) # Display the Dialog prompt eval "${DYNAMIC_DIALOG_BASE_STRING}" ;; "add" ) # Add an item to the list # # $2 name of item # $3 Icon status "wait, success, fail, error, pending or progress" # $4 Optional status text /bin/echo "listitem: add, title: ${2}, status: ${3}, statustext: ${4}" >> "${DIALOG_COMMAND_FILE}" ;; "buttonaction" ) # Change button 1 action /bin/echo 'button1action: "'${2}'"' >> "${DIALOG_COMMAND_FILE}" ;; "buttonchange" ) # change text of button 1 /bin/echo "button1text: ${2}" >> "${DIALOG_COMMAND_FILE}" ;; "buttondisable" ) # disable button 1 /bin/echo "button1: disable" >> "${DIALOG_COMMAND_FILE}" ;; "buttonenable" ) # Enable button 1 /bin/echo "button1: enable" >> "${DIALOG_COMMAND_FILE}" ;; "change" ) # Change the listitem Status # Increment the progress bar by static amount ($6) # Display the progress bar text ($5) /bin/echo "listitem: title: ${2}, status: ${3}, statustext: ${4}" >> "${DIALOG_COMMAND_FILE}" if [[ ! -z $5 ]]; then /bin/echo "progresstext: $5" >> "${DIALOG_COMMAND_FILE}" /bin/echo "progress: $6" >> "${DIALOG_COMMAND_FILE}" fi ;; "clear" ) # Clear the list and show an optional message /bin/echo "list: clear" >> "${DIALOG_COMMAND_FILE}" /bin/echo "message: ${2}" >> "${DIALOG_COMMAND_FILE}" ;; "delete" ) # Delete item from list /bin/echo "listitem: delete, title: ${2}" >> "${DIALOG_COMMAND_FILE}" ;; "destroy" ) # Kill the progress bar and clean up /bin/echo "quit:" >> "${DIALOG_COMMAND_FILE}" ;; "done" ) # Complete the progress bar and clean up /bin/echo "progress: complete" >> "${DIALOG_COMMAND_FILE}" /bin/echo "progresstext: $5" >> "${DIALOG_COMMAND_FILE}" ;; "icon" ) # set / clear the icon, pass <nil> if you want to clear the icon [[ -z ${2} ]] && /bin/echo "icon: none" >> "${DIALOG_COMMAND_FILE}" || /bin/echo "icon: ${2}" >> $"${DIALOG_COMMAND_FILE}" ;; "image" ) # Display an image and show an optional message /bin/echo "image: ${2}" >> "${DIALOG_COMMAND_FILE}" [[ ! -z ${3} ]] && /bin/echo "progresstext: $5" >> "${DIALOG_COMMAND_FILE}" ;; "infobox" ) # Show text message /bin/echo "infobox: ${2}" >> "${DIALOG_COMMAND_FILE}" ;; "infotext" ) # Show text message /bin/echo "infotext: ${2}" >> "${DIALOG_COMMAND_FILE}" ;; "show" ) # Activate the dialog box /bin/echo "activate:" >> $"${DIALOG_COMMAND_FILE}" ;; "title" ) # Set / Clear the title, pass <nil> to clear the title [[ -z ${2} ]] && /bin/echo "title: none:" >> "${DIALOG_COMMAND_FILE}" || /bin/echo "title: ${2}" >> "${DIALOG_COMMAND_FILE}" ;; "progress" ) # Increment the progress bar by static amount ($6) # Display the progress bar text ($5) /bin/echo "progress: ${6}" >> "${DIALOG_COMMAND_FILE}" /bin/echo "progresstext: ${5}" >> "${DIALOG_COMMAND_FILE}" ;; esac } function erase_support_files () { # Erase the support files and generally clean up after ourselves # # RETURNS: None /bin/rm -f "${LOCKFILE_PATH}" /bin/rm -f "${CURRENT_DEFERAL_EXPIRATION_TIMESTAMP_FILE}" /bin/rm -f "${DIALOG_COMMAND_FILE}" /bin/rm -f "${OVERLAY_ICON}" /bin/rm -f "${HARDWARE_ICON}" /bin/rm -f "${JSON_OPTIONS_FILE_PAT}" /bin/rm -f "${ANYCONNECT_PACKAGE_PATH}" } function unload_and_delete_daemon () { # Unloads the launch daemon from launchctl # # RETURNS: None /bin/launchctl unload -wF "${LAUNCH_DAEMON_PATH:r}" /bin/rm -f "${LAUNCH_DAEMON_PATH}" } function runAsUser () { if [ "$LoggedInUser" != "loginwindow" ]; then launchctl asuser "$uid" sudo -iu "$LoggedInUser" open "$@" else echo "no user logged in" # uncomment the exit command # to make the function exit with an error when no user is logged in # exit 1 fi } function Contains () { # Purpose: Scan for item inside an arry # Paramters: #1 - Pass entire array # #2 - Item to look for in array # Returns: Return 0 if element exists in array local list=$1[@] local elem=$2 for i in "${!list}" do [[ "$i" == "${elem}" ]] && return 0 done return 1 } function alltrim () { echo "${1}" | /usr/bin/xargs } function create_infobox_message() { ################################ # # Swift Dialog InfoBox message construct # ################################ SD_INFO_BOX_MSG="## System Info ##\\n" SD_INFO_BOX_MSG+="${MAC_CPU}<br>" SD_INFO_BOX_MSG+="${MAC_SERIAL_NUMBER}<br>" SD_INFO_BOX_MSG+="${MAC_RAM} RAM<br>" SD_INFO_BOX_MSG+="${FREE_DISK_SPACE}GB Available<br>" SD_INFO_BOX_MSG+="macOS ${MACOS_VERSION}<br>" } function get_hardware_platform_icon () { case $(alltrim "${MAC_HARDWARE_CLASS}") in "MacBook Air" ) HARDWARE_ICON="${ICON_DIRECTORY}/com.apple.macbookair-2018-gold.icns" ;; "MacBook Pro" ) HARDWARE_ICON="${ICON_DIRECTORY}/com.apple.macbookpro-16-silver.icns" ;; "Mac Mini" ) HARDWARE_ICON="${ICON_DIRECTORY}/com.apple.macmini-2020.icns" ;; "iMac" ) HARDWARE_ICON="${ICON_DIRECTORY}/com.apple.imac-2021-blue.icns" ;; "Mac Pro" ) HARDWARE_ICON="${ICON_DIRECTORY}/com.apple.macpro-2019.icns" ;; "Mac Studio" ) HARDWARE_ICON="${ICON_DIRECTORY}/com.apple.macstudio.icns" ;; esac } function cleanup_and_exit () { [[ -f ${JSON_OPTIONS} ]] && /bin/rm -rf ${JSON_OPTIONS} [[ -f ${TMP_FILE_STORAGE} ]] && /bin/rm -rf ${TMP_FILE_STORAGE} [[ -f ${DIALOG_COMMAND_FILE} ]] && /bin/rm -rf ${DIALOG_COMMAND_FILE} exit 0 } function unload_and_delete_daemon () { # Unloads the launch daemon from launchctl # # RETURNS: None /bin/launchctl unload -wF "${LAUNCH_DAEMON_PATH:r}" /bin/rm -f "${LAUNCH_DAEMON_PATH}" } function read_lockfile_pid () { # Reads a file which contains a PID. # # RETURNS: A string representation of a PID or nothing if # the file is empty or doesnt exist if [[ ! -e ${LOCKFILE_PATH} ]]; then return fi pid=$(cat "${LOCKFILE_PATH}") echo $pid } function clear_lock_file () { # Remove the lock file - we use this if we exit for a deferral and d # not want to clean up other files # # RETURNS: None /bin/rm -f "${LOCKFILE_PATH}" } function set_lock_file_with_pid () { printf $$ > "${LOCKFILE_PATH}" } typeset -a adapter typeset -a ip_address function get_nic_info { # Creates two arrays showing the Adapter name & IP address of all found IP address running on a system. # Detects for the presence of VPN adapter as well # # RETURNS: Two arrays (must be declared global outside of function) typeset -a nic_interfaces && nic_interfaces=( ${(f)"$( networksetup -listnetworkserviceorder | grep "Device:" | awk '{print $3, $NF}' )"} ) # Get ISP Info isp=$(curl -s https://ipecho.net/plain) adapter+="ISP" ip_address+=$isp # Go thru all of the adapters and get the name & IP address of each on for i ($nic_interfaces); do if [[ ${i} != *"bridge"* ]]; then adapter+=$( echo $i | awk '{print $1}' | tr -d ',' ) interface=$( echo $i | awk '{print $2}') ip=$(ifconfig ${interface::-1} | grep "inet " | awk '{print $2}') ip_address+=$ip fi done # If VPN is activate, get that info as well if [[ "$( echo 'state' | /opt/cisco/anyconnect/bin/vpn -s | grep -m 1 ">> state:" )" == *'Connected' ]]; then ip_address+=$(/opt/cisco/anyconnect/bin/vpn -s stats | grep 'Client Address (IPv4)' | awk -F ': ' '{ print $2 }' | xargs) adapter+="VPN" fi } function GetJAMFServer () { jamfpro_url=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url) } function GetJamfProAPIToken () { # This function uses Basic Authentication to get a new bearer token for API authentication. # Use user account's username and password credentials with Basic Authorization to request a bearer token. # # Parms expected: jampro_user, jamfpro_password, api_token=$(/usr/bin/curl -X POST --silent -u "${jamfpro_user}:${jamfpro_password}" "${jamfpro_url}/api/v1/auth/token" | plutil -extract token raw -) } function APITokenValidCheck () { # Verify that API authentication is using a valid token by running an API command # which displays the authorization details associated with the current API user. # The API call will only return the HTTP status code. api_authentication_check=$(/usr/bin/curl --write-out %{http_code} --silent --output /dev/null "${jamfpro_url}/api/v1/auth" --request GET --header "Authorization: Bearer ${api_token}") } function CheckAndRenewAPIToken () { # Verify that API authentication is using a valid token by running an API command # which displays the authorization details associated with the current API user. # The API call will only return the HTTP status code. APITokenValidCheck # If the api_authentication_check has a value of 200, that means that the current # bearer token is valid and can be used to authenticate an API call. if [[ ${api_authentication_check} == 200 ]]; then # If the current bearer token is valid, it is used to connect to the keep-alive endpoint. This will # trigger the issuing of a new bearer token and the invalidation of the previous one. api_token=$(/usr/bin/curl "${jamfpro_url}/api/v1/auth/keep-alive" --silent --request POST --header "Authorization: Bearer ${api_token}" | plutil -extract token raw -) else # If the current bearer token is not valid, this will trigger the issuing of a new bearer token # using Basic Authentication. GetJamfProAPIToken fi } function FileVaultRecoveryKeyValidCheck () { # Verify that a FileVault recovery key is available by running an API command # which checks if there is a FileVault recovery key present. # # The API call will only return the HTTP status code. filevault_recovery_key_check=$(/usr/bin/curl --write-out %{http_code} --silent --output /dev/null "${jamfpro_url}/api/v1/computers-inventory/$ID/filevault" --request GET --header "Authorization: Bearer ${api_token}") } function FileVaultRecoveryKeyRetrieval () { # Retrieves a FileVault recovery key from the computer inventory record. filevault_recovery_key_retrieved=$(/usr/bin/curl -sf --header "Authorization: Bearer ${api_token}" "${jamfpro_url}/api/v1/computers-inventory/$ID/filevault" -H "Accept: application/json" | plutil -extract personalRecoveryKey raw -) }

 

Be the first to reply!