Help me troubleshoot why this script is failing (bad time format)

atomczynski
Valued Contributor

I have a script which checks computer uptime. If more than seven days it kicks off another script.
Jamf Helper showing a message with some options to restart. Here is the script:

window="utility"
title="edited the title"
heading="Please restart your computer"
description="Your computer has not been restarted in at least seven days. A more frequent restart is recommended.

Doing so optimizes the performance of your computer as well as allows us to deploy security updates or new applications to you automatically.

Please restart now."

icon="/System/Library/CoreServices/Software Update.app/Contents/Resources/SoftwareUpdate.icns"




selection=$("/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper" -windowType "$window" -title "$title" -heading "$heading" -description "$description" -icon "$icon" -button2 "Restart"  -showDelayOptions "0, 60, 300, 3600, 7200" -button1 "Cancel" -cancelButton 1)

buttonClicked="${selection:$i-1}"
timeChosen="${selection%?}"

## Convert seconds to minutes for restart command
timeMinutes=$((timeChosen/60))

## Echoes for troubleshooting purposes
echo "Button clicked was: $buttonClicked"
echo "Time chosen was: $timeChosen"
echo "Time in minutes: $timeMinutes"

if [[ "$buttonClicked" == "2" ]] && [[ ! -z "$timeChosen" ]]; then
    echo "Restart button was clicked. Initiating restart in $timeMinutes minutes"
    shutdown -r +{$timeMinutes}
elif [[ "$buttonClicked" == "2" ]] && [[ -z "$timeChosen" ]]; then
    echo "Restart button was clicked. Initiating immediate restart"
    shutdown -r now
elif [ "$buttonClicked" == "1" ]; then
    echo "Cancel button clicked. Exiting..."
    exit 0
fi


exit

I see few different ways this fails:

Script result: 2020-04-20 13:35:57.067 jamfHelper[73095:5293090] GetInputSourceEnabledPrefs user file path = /Users/editedusername/Library/Preferences/com.apple.HIToolbox.plist
2020-04-20 13:35:57.067 jamfHelper[73095:5293090] GetInputSourceEnabledPrefs effective user id path = 0
2020-04-20 13:35:57.068 jamfHelper[73095:5293090] GetInputSourceEnabledPrefs user pref content = <CFBasicHash 0x7ff9c1457ad0 [0x7fffa0975af0]>{type = immutable dict, count = 6,
entries =>
    0 : <CFString 0x7ff9c14576f0 [0x7fffa0975af0]>{contents = "AppleTimeResID"} = <CFBasicHash 0x7ff9c144ed00 [0x7fffa0975af0]>{type = immutable dict, count = 1,
entries =>
    0 : smRoman = <CFNumber 0x37 [0x7fffa0975af0]>{value = +0, type = kCFNumberSInt64Type}
}

    1 : <CFString 0x7fffa08a9ab8 [0x7fffa0975af0]>{contents = "AppleEnabledInputSources"} = <CFArray 0x7ff9c142ebb0 [0x7fffa0975af0]>{type = immutable, count = 2, values = (
    0 : <CFBasicHash 0x7ff9c1456df0 [0x7fffa0975af0]>{type = immutable dict, count = 3,
entries =>
    0 : <CFString 0x7fffa08a7218 [0x7fffa0975af0]>{contents = "InputSourceKind"} = <CFString 0x7fffa08ee098 [0x7fffa0975af0]>{contents = "Keyboard Layout"}
    1 : <CFString 0x7fffa08a1d78 [0x7fffa0975af0]>{contents = "KeyboardLayout Name"} = U.S.
    2 : <CFString 0x7fffa08d9b78 [0x7fffa0975af0]>{contents = "KeyboardLayout ID"} = <CFNumber 0x37 [0x7fffa0975af0]>{value = +0, type = kCFNumberSInt64Type}
}

    1 : <CFBasicHash 0x7ff9c142eb70 [0x7fffa0975af0]>{type = immutable dict, count = 2,
entries =>
    0 : <CFString 0x7fffa08a7218 [0x7fffa0975af0]>{contents = "InputSourceKind"} = <CFString 0x7ff9c144f400 [0x7fffa0975af0]>{contents = "Non Keyboard Input Method"}
    1 : Bundle ID = <CFString 0x7ff9c144f430 [0x7fffa0975af0]>{contents = "com.apple.PressAndHold"}
}

)}
    2 : <CFString 0x7fffa08c9618 [0x7fffa0975af0]>{contents = "AppleSelectedInputSources"} = <CFArray 0x7ff9c144f570 [0x7fffa0975af0]>{type = immutable, count = 1, values = (
    0 : <CFBasicHash 0x7ff9c144f530 [0x7fffa0975af0]>{type = immutable dict, count = 2,
entries =>
    0 : <CFString 0x7fffa08a7218 [0x7fffa0975af0]>{contents = "InputSourceKind"} = <CFString 0x7ff9c142ebf0 [0x7fffa0975af0]>{contents = "Non Keyboard Input Method"}
    1 : Bundle ID = <CFString 0x7ff9c144f500 [0x7fffa0975af0]>{contents = "com.apple.PressAndHold"}
}

)}
    3 : <CFString 0x7ff9c1448540 [0x7fffa0975af0]>{contents = "AppleNumberResID"} = <CFBasicHash 0x7ff9c144f5b0 [0x7fffa0975af0]>{type = immutable dict, count = 1,
entries =>
    0 : smRoman = <CFNumber 0x37 [0x7fffa0975af0]>{value = +0, type = kCFNumberSInt64Type}
}

    4 : <CFString 0x7ff9c1438b30 [0x7fffa0975af0]>{contents = "AppleDateResID"} = <CFBasicHash 0x7ff9c1457a90 [0x7fffa0975af0]>{type = immutable dict, count = 1,
entries =>
    0 : smRoman = <CFNumber 0x37 [0x7fffa0975af0]>{value = +0, type = kCFNumberSInt64Type}
}

    5 : <CFString 0x7fffa091db78 [0x7fffa0975af0]>{contents = "AppleCurrentKeyboardLayoutInputSourceID"} = <CFString 0x7fffa093bcf8 [0x7fffa0975af0]>{contents = "com.apple.keylayout.US"}
}
Button clicked was: 2
Time chosen was: 300
Time in minutes: 5
Restart button was clicked. Initiating restart in 5 minutes
shutdown: bad time format

or
Script result: Button clicked was: 2
Time chosen was: 3600
Time in minutes: 60
Restart button was clicked. Initiating restart in 60 minutes
shutdown: bad time format

Ideas?

4 REPLIES 4

joshuaaclark
Contributor

I think

shutdown -r +{$timeMinutes}

should be

shutdown -r +${timeMinutes}

joshuaaclark
Contributor

Also for funsies, here is some code to tell the user exactly how long their Mac has been on:

#!/bin/bash

# ====== THE COMPUTER HAS BEEN ON FOR THIS LONG ===========
string2=$(uptime | 
sed s/^.*up// | 
awk -F, '{ if ( $3 ~ /user/ ) { print $1 $2 } else { print $1 }} ' | 
sed -e 's/:/ hours /' -e 's/ min//' -e 's/$/ minutes/' | 
sed 's/^ *//')
howlong=$(echo $string2)
# ===========================================================

window="utility"
title="edited the title"
heading="Please restart your computer" # Edited here ==/
description="Your computer has not been restarted in $howlong. A more frequent restart is recommended.

Doing so optimizes the performance of your computer as well as allows us to deploy security updates or new applications to you automatically.

Please restart now."

shaquir
Contributor III

Looks like @joshuaaclark caught it with the curly bracket placement!
It may be helpful to add an additional alert/prompt for users that select a time past 5 minutes. I'm sure I'd forget a reboot timer I set over a hour ago.
You can check this thread as a reference for how other users have made this happen https://www.jamf.com/jamf-nation/discussions/27844/

tlarkin
Honored Contributor

So some tips for running scripts in general

Inside your script you can add:

set -x

which will print out the script line by line, you can also run

zsh -x /path/to/script

This is the same but you don't have to add the set environment variable. You can also toss your code in a nifty app like shell check.

To calculate days since last reboot (or uptime) I like to take the approach of getting just a value of days

# get the last start time from the kernel, returns epoch value
% boot_time=$(sysctl -n kern.boottime | awk '{ print $4 }' | sed 's/,//')
# get current date in epoch
% now=$(date +%s)
# diff them to get an epoch difference and divide by 86400 to get number of days
% diff=$(((($now - $boot_time) / 86400)))
# returns number of days since I have last rebooted, 0 is less than a day
% echo $diff
13

This returns a value of days the system has not been rebooted based of the kernel boot time. I take this approach so I can store this value in my data sets and use it later on, but also because it makes it easy to just use integer values, although in shell you will be evaluating it as a string.

Also, to make your code more readable you can split lines with

some unix command | some other unix command | 
continuing on this line now | another pipe 
| last command

`
This makes it a bit more human readable and you don't have to scroll 5 miles to the right in your editor