When I added @EdLuo's script to my policy, I appear to be stuck in a loop.. Has anyone experienced this?
Here is the full script that I am using. I made a few changes from script that I found on Jamf.
Credit goes to you and Mauricio
https://www.jamf.com/jamf-nation/discussions/35899/verify-password-is-correct
#!/bin/bash
#########################################################################################
#
# FUNCTIONS
#
#########################################################################################
wrongUserPassword() {
userResponce=$(sudo -u "$userName" osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theTextReturned to "nil"
set theIcon to POSIX file "/Users/Shared/logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set enterPassword to "Enter your password to start the update"
set passwordWrong to "Incorrect Password"
set errorPasswordText to passwordWrong & return & enterPassword
set theResponse to display dialog {errorPasswordText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
validatePassword "$userResponce"
}
noUserPassword() {
userResponce=$(sudo -u "$userName" osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theTextReturned to "nil"
set theIcon to POSIX file "/Users/Shared/logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set enterPassword to "Enter your password to start the update"
set passwordEmpty to "The password is empty."
set errorPasswordText to passwordEmpty & return & enterPassword
set theResponse to display dialog {errorPasswordText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
validatePassword "$userResponce"
}
promptUserPassword() {
userResponce=$(sudo -u "$userName" osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theTextReturned to "nil"
set theIcon to POSIX file "/Users/Shared/logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set changesText to "One or more Apple Updates are availalbe." & return & "It may take 30-60 minutes to complete." & return & "To continue with macOS update" & return & return & "Enter login password for $userName"
set theResponse to display dialog {changesText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
}
verifyPassword() {
dscl . authonly "$userName" "$userResponce" &> /dev/null; resultCode=$?
if [ "$resultCode" -eq 0 ];then
echo "Password Check: PASSED"
else
# Prompt for User Password
echo "Password Check: WRONG PASSWORD"
wrongUserPassword
fi
}
validatePassword() {
case "$userResponce" in
"nopassword" ) echo "Password Check: NO PASSWORD" & noUserPassword ;;
"cancelled" ) echo "Password Check: Time Out" ;;
* ) verifyPassword ;;
esac
}
##########################################################################################
#
# SCRIPT CONTENTS
#
##########################################################################################
# Get the Username of the currently logged user
userName=$(ls -la /dev/console | cut -d " " -f 4)
# Ask the logged user for the password
promptUserPassword "$userName"
# Check is password is correct
validatePassword "$userResponce"
if [ $userResponce = "cancelled" ]; then
echo "Password entry was cancelled"
else
echo "Running updates for Apple Silicon Mac"
expect -c "
set timeout -1
log_user 0
spawn login $userName
expect "Password:"
send "{${userResponce}}"
send
spawn sh -c {sudo /usr/sbin/softwareupdate -iaR}
expect "Password:"
send "{${userResponce}}"
send
expect "Password:"
send "{${userResponce}}"
send
expect eof
"
fi
Hi, I am currently getting this on a M1 MacBook Air using the above script. Can anyone help to execute the script fully?
Thx, Alex

If you don't want to prompt the user at all, you can make a bash or python script that runs the Download and Install Updates management command for you. Add the script to a user interaction policy to give the user the option to defer the update.

apiUsername="apiaccount"
apiPassword="apipassword"
jamfProURL="https://yourorg.jamfcloud.com"
macSerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')
jamfProCompID=$(curl -s -u $apiUsername:$apiPassword -H "Accept: text/xml" "$jamfProURL"/JSSResource/computers/serialnumber/"$macSerial" | xmllint --xpath '/computer/general/id/text()' -)
/usr/bin/curl -s -X POST -H "Content-Type: text/xml" -u ${apiUsername}:${apiPassword} ${jamfProURL}/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${jamfProCompID}
I gave up on my script. I'm using Nudge for macOS 11.x and 12.x. It is fairly reliable.
https://marketplace.jamf.com/details/nudge/
If you don't want to prompt the user at all, you can make a bash or python script that runs the Download and Install Updates management command for you. Add the script to a user interaction policy to give the user the option to defer the update.

apiUsername="apiaccount"
apiPassword="apipassword"
jamfProURL="https://yourorg.jamfcloud.com"
macSerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')
jamfProCompID=$(curl -s -u $apiUsername:$apiPassword -H "Accept: text/xml" "$jamfProURL"/JSSResource/computers/serialnumber/"$macSerial" | xmllint --xpath '/computer/general/id/text()' -)
/usr/bin/curl -s -X POST -H "Content-Type: text/xml" -u ${apiUsername}:${apiPassword} ${jamfProURL}/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${jamfProCompID}
The script communicates but doesn't fully execute. The command completes but the computer doesn't update. I'm still on 11.6.2. I thought there was something wrong with:
action/Default/
but I tried this one as well:
/action/InstallForceRestart/
I'm a bit confused by the logs, it looks to me like it did try to install Big Sur 11.6.3 and succeeded:
default 2022-02-03 11:31:03.665716 -0800 SoftwareUpdateNotificationManager SUOSUNotificationUpdateService: Install did begin for updates: (
"<SUOSUProduct: MSU_UPDATE_20G415_patch_11.6.3>"
)
default 2022-02-03 11:31:03.665723 -0800 SoftwareUpdateNotificationManager SUOSUNotificationUpdateService: MDM install did begin
default 2022-02-03 11:31:03.665756 -0800 SoftwareUpdateNotificationManager MDM major status: {
"MSU_UPDATE_20G415_patch_11.6.3" = {
phase = downloading;
progress = 0;
};
phase = downloading;
productKeys = (
"MSU_UPDATE_20G415_patch_11.6.3"
);
progress = 0;
}
default 2022-02-03 11:31:03.774389 -0800 SoftwareUpdateNotificationManager SUOSUNotificationUpdateService: Install did finish successfully for updates (
"<SUOSUProduct: MSU_UPDATE_20G415_patch_11.6.3>"
)
I hate to revive an old thread, but I was curious to see if anyone settled on a way to install software updates, but still do it though self service?
We are working on the API call to initiate the MDM command that @bwoods posted, but we have some setup to do. We're a little (aka alot) behind on the OS and hardware front, we are running mostly Catalina and intel because the pandemic has had us working from home for two years and users, well you know users. But we are about to get a bunch of Apple Silicon machines.
Thanks!
The script communicates but doesn't fully execute. The command completes but the computer doesn't update. I'm still on 11.6.2. I thought there was something wrong with:
action/Default/
but I tried this one as well:
/action/InstallForceRestart/
I'm a bit confused by the logs, it looks to me like it did try to install Big Sur 11.6.3 and succeeded:
default 2022-02-03 11:31:03.665716 -0800 SoftwareUpdateNotificationManager SUOSUNotificationUpdateService: Install did begin for updates: (
"<SUOSUProduct: MSU_UPDATE_20G415_patch_11.6.3>"
)
default 2022-02-03 11:31:03.665723 -0800 SoftwareUpdateNotificationManager SUOSUNotificationUpdateService: MDM install did begin
default 2022-02-03 11:31:03.665756 -0800 SoftwareUpdateNotificationManager MDM major status: {
"MSU_UPDATE_20G415_patch_11.6.3" = {
phase = downloading;
progress = 0;
};
phase = downloading;
productKeys = (
"MSU_UPDATE_20G415_patch_11.6.3"
);
progress = 0;
}
default 2022-02-03 11:31:03.774389 -0800 SoftwareUpdateNotificationManager SUOSUNotificationUpdateService: Install did finish successfully for updates (
"<SUOSUProduct: MSU_UPDATE_20G415_patch_11.6.3>"
)
Use "install" instead of "Default". I need to fix my post.
@bwoods is correct. I changed it to "install" after I spoke to JAMF support. I have had success everytime since then.
/action/install/
They told me this was their official recommendation for updating the OS. They shared this API doc. https://developer.jamf.com/jamf-pro/reference/createcomputercommandbycommandandaction
I was also told,
"The default actions for updates are "latest, non-major" version when done via the API.
The new feature in 10.36 will make major updates possible.
The reason 'InstallForceRestart' didn't work is because it isn't supported yet (it will be in 10.36), so it just generates a DownloadOnly action.
So instead we should use just 'Install" which generates an 'InstallASAP' action."
@bwoods is correct. I changed it to "install" after I spoke to JAMF support. I have had success everytime since then.
/action/install/
They told me this was their official recommendation for updating the OS. They shared this API doc. https://developer.jamf.com/jamf-pro/reference/createcomputercommandbycommandandaction
I was also told,
"The default actions for updates are "latest, non-major" version when done via the API.
The new feature in 10.36 will make major updates possible.
The reason 'InstallForceRestart' didn't work is because it isn't supported yet (it will be in 10.36), so it just generates a DownloadOnly action.
So instead we should use just 'Install" which generates an 'InstallASAP' action."
@bwoods @cucaracha When I run the command to actually install the update, I keep getting this response:
<html>
<head>
<title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unauthorized</p>
<p>The request requires user authentication</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>
The api user I created works fine for getting the machine ID, so I dunno what I am doing wrong here.
Did I screwed something up with the settings in our JAMF Server for the account I put in here:
apiUsername="apiaccount"
I don't want to open everything up, cause I won't know what worked and it's not very secure to have godmode enabled.
Any ideas? Thanks.
Hi, I am currently getting this on a M1 MacBook Air using the above script. Can anyone help to execute the script fully?
Thx, Alex

I had to edit out the blank send commands, like so:
AdminUser=$4
AdminPass=$5
#Hope this works for Intel & Apple Silicon
echo "Running updates"
expect -c "
set timeout -1
spawn login $AdminUser
expect "Password:"
send "{${AdminPass}}"
spawn sh -c {sudo /usr/sbin/softwareupdate -iaR --verbose | tee -a /var/log/jamf.log}
expect "Password:"
send "{${AdminPass}}"
expect "Password:"
send "{${AdminPass}}"
expect eof
"
Credit to @DBrowning
I figured the "send " parts of that little expect block weren't acting like newlines or returns or anything so I removed them.
Then I thought I'd just use a local admin:pass to run the update. That way we get around the fact that our users don't have sudo rights.
It appears to be working on an intel I'm testing right now, and I'll test on an M1 as soon as I get a chance.
Note the parameter numbers so you don't have to have user names or passwords written into a script.
Hope that helps.
@bwoods @cucaracha When I run the command to actually install the update, I keep getting this response:
<html>
<head>
<title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unauthorized</p>
<p>The request requires user authentication</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>
The api user I created works fine for getting the machine ID, so I dunno what I am doing wrong here.
Did I screwed something up with the settings in our JAMF Server for the account I put in here:
apiUsername="apiaccount"
I don't want to open everything up, cause I won't know what worked and it's not very secure to have godmode enabled.
Any ideas? Thanks.
I have everything turned on, but I would think "Send Computer Remote Command to Download and Install macOS Update" needs to be on. Under Privileges > Jamf Pro Server Actions. Also "View MDM command information in Jamf Pro API"
@bwoods @cucaracha When I run the command to actually install the update, I keep getting this response:
<html>
<head>
<title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unauthorized</p>
<p>The request requires user authentication</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>
The api user I created works fine for getting the machine ID, so I dunno what I am doing wrong here.
Did I screwed something up with the settings in our JAMF Server for the account I put in here:
apiUsername="apiaccount"
I don't want to open everything up, cause I won't know what worked and it's not very secure to have godmode enabled.
Any ideas? Thanks.
It looks like your api account may not have the proper permissions. Give it a try with your admin creds for testing.
So, this script does a download only and I still need to login and finish the updates? It seems it just takes the place of running the Management command on every computer, right? Until the 'InstallForceRestart' is supported?
It looks like your api account may not have the proper permissions. Give it a try with your admin creds for testing.
I tried it with a different user and I was able to run it as a local script and got to this output:
<?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>ScheduleOSUpdateScan</name><command_uuid>5c3de1d2-ab73-40bf-8638-b58d67c154f4</command_uuid><computer_id>3695</computer_id></command></computer_command>
Then I got a pop-up that needed admin authentication for SoftwareUpdate to be allowed to make some change or other. I didn't get a screenshot, sorry. This is as far as I've gotten with trying to update an M1 with a script or policy.
Is the update just supposed to install right after I run this, or is there something else I need to do?
Thanks!
So, this script does a download only and I still need to login and finish the updates? It seems it just takes the place of running the Management command on every computer, right? Until the 'InstallForceRestart' is supported?
+1 on this question.
I tried it with a different user and I was able to run it as a local script and got to this output:
<?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>ScheduleOSUpdateScan</name><command_uuid>5c3de1d2-ab73-40bf-8638-b58d67c154f4</command_uuid><computer_id>3695</computer_id></command></computer_command>
Then I got a pop-up that needed admin authentication for SoftwareUpdate to be allowed to make some change or other. I didn't get a screenshot, sorry. This is as far as I've gotten with trying to update an M1 with a script or policy.
Is the update just supposed to install right after I run this, or is there something else I need to do?
Thanks!
Are your bootstrap tokens escrowed and are your macs supervised? The update downloads and updates the computer automatically after about 20-40 minutes. (some have even reported longer)

So, this script does a download only and I still need to login and finish the updates? It seems it just takes the place of running the Management command on every computer, right? Until the 'InstallForceRestart' is supported?
It downloads and updates the mac. From what I can see, the user must be logged in.
Are your bootstrap tokens escrowed and are your macs supervised? The update downloads and updates the computer automatically after about 20-40 minutes. (some have even reported longer)

Aw nuts. My bad. I'll have to get that set up. thanks!
Aw nuts. My bad. I'll have to get that set up. thanks!
And I'm back again, just to report what I've got so far.
My test machine has bootstrap token enabled and escrowed. The API user has the correct permissions. The little script is setup to be run from self service in a simple policy. Here's the script:
#!/bin/sh
# apiMDMupdatesoftware.sh
# api call to send MDM command to a machine to update apple system software.
apiUsername=$4
apiPassword=$(echo ${5} | base64 --decode)
jamfProURL="https://jamf01.spimageworks.com:8443"
macSerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')
jamfProCompID=$(curl -s -u $apiUsername:$apiPassword -H "Accept: text/xml" "$jamfProURL"/JSSResource/computers/serialnumber/"$macSerial" | xmllint --xpath '/computer/general/id/text()' -)
/usr/bin/curl -s -X POST -H "Content-Type: text/xml" -u ${apiUsername}:${apiPassword} ${jamfProURL}/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${jamfProCompID}
I get this little pop-up when I first run the policy:

Which is fine for now, I'm just trying to get this to work.
Here's the output from the logs on JAMF:
Script result: <?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>ScheduleOSUpdateScan</name><command_uuid>10ac1fea-25df-4b15-a69e-ca8b66432025</command_uuid><computer_id>3706</computer_id></command></computer_command>
But then nothing happens. I let my test machine run for hours and there was no update. I also kept an eye on the update processes in Activity Monitor under Network and nothing really seemed like it was downloading.
Any help would be much appreciated. Thanks!
And I'm back again, just to report what I've got so far.
My test machine has bootstrap token enabled and escrowed. The API user has the correct permissions. The little script is setup to be run from self service in a simple policy. Here's the script:
#!/bin/sh
# apiMDMupdatesoftware.sh
# api call to send MDM command to a machine to update apple system software.
apiUsername=$4
apiPassword=$(echo ${5} | base64 --decode)
jamfProURL="https://jamf01.spimageworks.com:8443"
macSerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')
jamfProCompID=$(curl -s -u $apiUsername:$apiPassword -H "Accept: text/xml" "$jamfProURL"/JSSResource/computers/serialnumber/"$macSerial" | xmllint --xpath '/computer/general/id/text()' -)
/usr/bin/curl -s -X POST -H "Content-Type: text/xml" -u ${apiUsername}:${apiPassword} ${jamfProURL}/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${jamfProCompID}
I get this little pop-up when I first run the policy:

Which is fine for now, I'm just trying to get this to work.
Here's the output from the logs on JAMF:
Script result: <?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>ScheduleOSUpdateScan</name><command_uuid>10ac1fea-25df-4b15-a69e-ca8b66432025</command_uuid><computer_id>3706</computer_id></command></computer_command>
But then nothing happens. I let my test machine run for hours and there was no update. I also kept an eye on the update processes in Activity Monitor under Network and nothing really seemed like it was downloading.
Any help would be much appreciated. Thanks!
Aw nuts. I just had a thought. We disable the Software Update Pref Pane in system prefs with the Restrictions payload, as well as Software Update Notifications. I'm not sure if this effects the MDM command.
Aw nuts. I just had a thought. We disable the Software Update Pref Pane in system prefs with the Restrictions payload, as well as Software Update Notifications. I'm not sure if this effects the MDM command.
The next time you run this command, look up the computer you ran it on and navigate to the management tab. Post a screenshot of what you see.
#!/bin/bash
## Documentation Text V3
##
## Logging during runtime
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/private/var/Path/to/Local/Log/ScheduleOSUpdate.log 2>&1
exec 2>>/private/var/Path/to/Local/LogScheduleOSUpdateErr.log 4>&2
jssurl="JamfProURL"
jamfManagementURL="JamfproURL"
apiuser="apiuser"
apipass="apipassword"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
<<'DOCUMENTATION'
Note the – The computer needs to be on power, or nothing happens
The user will be prompted for their password if it's on power added to your saved items
curl -sSu "$destinationJSSuser:$destinationJSSpw" $JSSURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${id} -X "POST"
Also the machine needs to be supervised
If it's not supervised doing the FileVault 2 key re-escrow will supervise it in macOS 11
DOCUMENTATION
clearfailedmdmcommands() {
/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443/JSSResource/commandflush/computers/id/"$computerID"/status/Failed -X DELETE
}
getjsscomputerid() {
computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath -e "/computer[1]/general/id/text()")
}
getfailedmdmcommands() {
xmlresult=$(/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443//JSSResource/computerhistory/serialnumber/"$serial"/subset/Commands -X GET -H "accept: application/xml" | /usr/bin/xpath -e "/computer_history/commands/failed")
}
startupdate() {
#curl -s -f -X "POST" "$jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/$jamfComputerID"
#curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
}
echo "updating device"
####### SCRIPT
getfailedmdmcommands
# An empty failed XML node will look like this: <failed />
parseresult=$(/bin/echo "$xmlresult" | /usr/bin/grep "<failed />")
exitcode=$(/bin/echo $?)
# Clear failed MDM commands if they exist
if [ "$exitcode" != 0 ]; then
getjsscomputerid
/bin/echo "Removing failed MDM commands ..."
clearfailedmdmcommands
result="Removed Failed MDM Commands"
echo "starting MacOS SoftwareUpdate"
startupdate
else
/bin/echo "No failed MDM commands exist."
result="No Failed MDM Commands Exist"
echo "starting MacOS SoftwareUpdate"
getjsscomputerid
startupdate
fi
/bin/echo "<result>$result</result>"
exit
The next time you run this command, look up the computer you ran it on and navigate to the management tab. Post a screenshot of what you see.
Sorry, I got side tracked testing out Nudge, which turns out to be a bit of a waste for my environment.
I guess it's back to the MDM command. I'll get that screenshot.
#!/bin/bash
## Documentation Text V3
##
## Logging during runtime
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/private/var/Path/to/Local/Log/ScheduleOSUpdate.log 2>&1
exec 2>>/private/var/Path/to/Local/LogScheduleOSUpdateErr.log 4>&2
jssurl="JamfProURL"
jamfManagementURL="JamfproURL"
apiuser="apiuser"
apipass="apipassword"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
<<'DOCUMENTATION'
Note the – The computer needs to be on power, or nothing happens
The user will be prompted for their password if it's on power added to your saved items
curl -sSu "$destinationJSSuser:$destinationJSSpw" $JSSURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${id} -X "POST"
Also the machine needs to be supervised
If it's not supervised doing the FileVault 2 key re-escrow will supervise it in macOS 11
DOCUMENTATION
clearfailedmdmcommands() {
/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443/JSSResource/commandflush/computers/id/"$computerID"/status/Failed -X DELETE
}
getjsscomputerid() {
computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath -e "/computer[1]/general/id/text()")
}
getfailedmdmcommands() {
xmlresult=$(/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443//JSSResource/computerhistory/serialnumber/"$serial"/subset/Commands -X GET -H "accept: application/xml" | /usr/bin/xpath -e "/computer_history/commands/failed")
}
startupdate() {
#curl -s -f -X "POST" "$jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/$jamfComputerID"
#curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
}
echo "updating device"
####### SCRIPT
getfailedmdmcommands
# An empty failed XML node will look like this: <failed />
parseresult=$(/bin/echo "$xmlresult" | /usr/bin/grep "<failed />")
exitcode=$(/bin/echo $?)
# Clear failed MDM commands if they exist
if [ "$exitcode" != 0 ]; then
getjsscomputerid
/bin/echo "Removing failed MDM commands ..."
clearfailedmdmcommands
result="Removed Failed MDM Commands"
echo "starting MacOS SoftwareUpdate"
startupdate
else
/bin/echo "No failed MDM commands exist."
result="No Failed MDM Commands Exist"
echo "starting MacOS SoftwareUpdate"
getjsscomputerid
startupdate
fi
/bin/echo "<result>$result</result>"
exit
Does this work for you in your environment? Is it reliable?
Here I formatted your script for this thread, easier to read that way.
#!/bin/bash
## Documentation Text V3
##
## Logging during runtime
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/private/var/Path/to/Local/Log/ScheduleOSUpdate.log 2>&1
exec 2>>/private/var/Path/to/Local/LogScheduleOSUpdateErr.log 4>&2
jssurl="JamfProURL"
jamfManagementURL="JamfproURL"
apiuser="apiuser"
apipass="apipassword"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
<<'DOCUMENTATION'
Note the – The computer needs to be on power, or nothing happens
The user will be prompted for their password if it's on power added to your saved items
curl -sSu "$destinationJSSuser:$destinationJSSpw" $JSSURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${id} -X "POST"
Also the machine needs to be supervised
If it's not supervised doing the FileVault 2 key re-escrow will supervise it in macOS 11
DOCUMENTATION
clearfailedmdmcommands() {
/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443/JSSResource/commandflush/computers/id/"$computerID"/status/Failed -X DELETE
}
getjsscomputerid() {
computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath -e "/computer[1]/general/id/text()")
}
getfailedmdmcommands() {
xmlresult=$(/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443//JSSResource/computerhistory/serialnumber/"$serial"/subset/Commands -X GET -H "accept: application/xml" | /usr/bin/xpath -e "/computer_history/commands/failed")
}
startupdate() {
#curl -s -f -X "POST" "$jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/$jamfComputerID"
#curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
}
echo "updating device"
####### SCRIPT
getfailedmdmcommands
# An empty failed XML node will look like this: <failed />
parseresult=$(/bin/echo "$xmlresult" | /usr/bin/grep "<failed />")
exitcode=$(/bin/echo $?)
# Clear failed MDM commands if they exist
if [ "$exitcode" != 0 ]; then
getjsscomputerid
/bin/echo "Removing failed MDM commands ..."
clearfailedmdmcommands
result="Removed Failed MDM Commands"
echo "starting MacOS SoftwareUpdate"
startupdate
else
/bin/echo "No failed MDM commands exist."
result="No Failed MDM Commands Exist"
echo "starting MacOS SoftwareUpdate"
getjsscomputerid
startupdate
fi
/bin/echo "<result>$result</result>"
exit
Does this work for you in your environment? Is it reliable?
Here I formatted your script for this thread, easier to read that way.
#!/bin/bash
## Documentation Text V3
##
## Logging during runtime
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/private/var/Path/to/Local/Log/ScheduleOSUpdate.log 2>&1
exec 2>>/private/var/Path/to/Local/LogScheduleOSUpdateErr.log 4>&2
jssurl="JamfProURL"
jamfManagementURL="JamfproURL"
apiuser="apiuser"
apipass="apipassword"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')
<<'DOCUMENTATION'
Note the – The computer needs to be on power, or nothing happens
The user will be prompted for their password if it's on power added to your saved items
curl -sSu "$destinationJSSuser:$destinationJSSpw" $JSSURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${id} -X "POST"
Also the machine needs to be supervised
If it's not supervised doing the FileVault 2 key re-escrow will supervise it in macOS 11
DOCUMENTATION
clearfailedmdmcommands() {
/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443/JSSResource/commandflush/computers/id/"$computerID"/status/Failed -X DELETE
}
getjsscomputerid() {
computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath -e "/computer[1]/general/id/text()")
}
getfailedmdmcommands() {
xmlresult=$(/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443//JSSResource/computerhistory/serialnumber/"$serial"/subset/Commands -X GET -H "accept: application/xml" | /usr/bin/xpath -e "/computer_history/commands/failed")
}
startupdate() {
#curl -s -f -X "POST" "$jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/$jamfComputerID"
#curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
}
echo "updating device"
####### SCRIPT
getfailedmdmcommands
# An empty failed XML node will look like this: <failed />
parseresult=$(/bin/echo "$xmlresult" | /usr/bin/grep "<failed />")
exitcode=$(/bin/echo $?)
# Clear failed MDM commands if they exist
if [ "$exitcode" != 0 ]; then
getjsscomputerid
/bin/echo "Removing failed MDM commands ..."
clearfailedmdmcommands
result="Removed Failed MDM Commands"
echo "starting MacOS SoftwareUpdate"
startupdate
else
/bin/echo "No failed MDM commands exist."
result="No Failed MDM Commands Exist"
echo "starting MacOS SoftwareUpdate"
getjsscomputerid
startupdate
fi
/bin/echo "<result>$result</result>"
exit
yes it works as long as the device is on and available it works...