Posted on 03-08-2019 10:54 AM
I've been fumbling around with this for a bit now and I'm feeling pretty stuck.
I'm trying to get all the iOS devices in a specific SmartGroup to reboot via a script.
groupid=104
jssAddress="https://myurl:8443"
devices=$(curl -sku "${jssAPIUsername}:${jssAPIPassword}" -H "Content-Type: text/xml" "${jssAddress}/JSSResource/mobiledevicegroups/id/${groupid}" | xmllint --xpath //id - | sed -e "s/<id>${groupid}</id><id>-1</id>//" | sed -e 's/</id><id>/,/g' | sed -e 's/id/id_list/g' )
#devices=$(curl -sku "${jssAPIUsername}:${jssAPIPassword}" -H "Content-Type: text/xml" "${jssAddress}/JSSResource/mobiledevicegroups/id/${groupid}" | xmllint --xpath //id - | sed -e "s/<id>${groupid}</id>//" | sed -e 's/<id>-1</>//' )
#devices="<id>8</id>"
data="<mobile_device_command><general><command>RestartDevice</command></general><mobile_devices><mobile_device><id>${devices}</id></mobile_device></mobile_devices></mobile_device_command>"
#echo $devices
echo "~~~~~~~~~~~~"
echo $data
curl -sku "${jssAPIUsername}:${jssAPIPassword}" -H "Content-Type: text/xml" "${jssAddress}/JSSResource/mobiledevicecommands/command" -d $data -X POST
I get "Bad Request" "Unable to match mobile device"
It doesn't appear to have pushed to any of the devices.
Does anyone have some experience with this that wants to lend a set of eyes? The troubling part is getting the devices selected. Operating on a single device isn't a problem.
Thanks in advance for any help provided.
Posted on 03-08-2019 11:18 AM
Probably going to have to put the devices in an array and then have a foreach and send the command to each device
Posted on 03-08-2019 11:33 AM
yuck, really?
Below is pretty much verbatim what the API example shows and returns "Bad Request" "Unable to match mobile_device"
curl -sku "${jssAPIUsername}:${jssAPIPassword}" -H "accept: application/xml" -X POST "${jssAddress}/JSSResource/mobiledevicecommands/command/RestartDevice/id/8%2C18%2C39%2C40%2C43%2C44%2C45%2C46%2C47%2C48%2C49%2C50%2C51%2C65%2C112%2C116%2C127%2C132%2C141%2C193%2C206%2C222%2C271%2C321%2C328%2C367%2C375%2C418%2C426%2C428%2C433%2C439%2C452%2C470%2C475%2C479%2C489%2C500%2C502%2C528%2C534%2C544%2C545%2C574%2C585%2C592%2C596%2C598%2C601%2C615%2C632%2C635%2C661%2C667%2C682%2C690%2C700%2C703%2C707%2C736%2C752%2C1182%2C1183%2C1184%2C1185%2C1186%2C1187%2C1188%2C1189%2C1190%2C1191%2C1192%2C1201%2C1202%2C1203%2C1252%2C1253%2C1254%2C1255%2C1256%2C1257%2C1258%2C1259%2C1260%2C1261%2C1262%2C1264%2C1265%2C1266%2C1267%2C1268%2C1269%2C1270%2C1271%2C1272%2C1273%2C1274%2C1275%2C1276%2C1277%2C1278%2C1279%2C1280%2C1281%2C1339%2C2030%2C2084%2C2136%2C2143%2C2726%2C2727%2C2728%2C2729%2C2730%2C2731%2C2732%2C2733%2C2734%2C2735%2C2736%2C2737%2C2738%2C2739%2C2740%2C2741%2C2742%2C2743%2C2744%2C2745%2C2746%2C2747%2C2748%2C2749%2C2750%2C2751%2C2752%2C2753%2C2754%2C2755%2C2756%2C2757%2C2758%2C2759%2C2760%2C2761%2C2762%2C2763%2C2764%2C2765%2C2766%2C2767%2C2768%2C2769%2C2770%2C2771%2C2772%2C2773%2C2774%2C2775%2C2776%2C2777%2C2778%2C2779%2C2780%2C2781%2C2782%2C2783%2C2784%2C2785%2C2786%2C2787%2C2788%2C2789%2C2790%2C2791%2C2792%2C2793%2C2794%2C2795%2C2796%2C2797%2C2798%2C2799%2C2800%2C2801%2C2802%2C2803%2C2804%2C2805%2C2806%2C2807%2C2808%2C2809%2C2810%2C2811%2C2812%2C2813%2C2814%2C2815%2C2817%2C3303%2C3304%2C3305%2C3306%2C3307%2C3308%2C3309%2C3310%2C3311%2C3312%2C3313%2C3360%2C3361%2C3362%2C3363%2C3364%2C3365%2C3366%2C3367%2C3368%2C3369%2C3370%2C3371%2C3372%2C3373%2C3374%2C3375%2C3376%2C3377%2C3378%2C3379%2C3380%2C3381%2C3382%2C3383%2C3384%2C3385%2C3386%2C3387%2C3388%2C3389%2C3390%2C3391%2C3392%2C3393%2C3394%2C3395%2C3396%2C3397%2C3398%2C3399%2C3400%2C3401%2C3402%2C3403%2C3404%2C3405%2C3406%2C3407%2C3408%2C3409"
Posted on 03-08-2019 11:58 AM
Well dumping them into an array and running a bash for loop did the trick. It looks like there are still devices getting that error, but it isn't stopping the rest of them.
jssAPIUsername="USER"
jssAPIPassword="PASS"
groupid=32
jssAddress="https://myjamf:8443"
devices=$(curl -sku "${jssAPIUsername}:${jssAPIPassword}" -H "Content-Type: text/xml" "${jssAddress}/JSSResource/mobiledevicegroups/id/${groupid}" | xmllint --xpath //id - | sed -e "s/<id>${groupid}</id><id>-1</id>//" | sed -e 's/</id><id>/,/g' | sed -e 's/<[/]?id>//g' )
echo "~~~~~~~~~~~~"
IFS=',' read -ra devIDs <<< "$devices"
for x in "${devIDs[@]}";
do
data="<mobile_device_command><general><command>RestartDevice</command></general><mobile_devices><mobile_device><id>${x}</id></mobile_device></mobile_devices></mobile_device_command>"
curl -sku "${jssAPIUsername}:${jssAPIPassword}" -H "Content-Type: text/xml" "${jssAddress}/JSSResource/mobiledevicecommands/command" -d $data -X POST
echo ""
echo $x
echo "~~~~~~~~~~~~"
sleep 5
done
Needs lots of cleanup, but here it is.
Posted on 03-08-2019 12:03 PM
I've done something similar with a Blank Push command.
Let's see.. you are POSTING so get rid of the -H section. The ID list needs to be comma separated not %2C.. assuming that is what you get in $devices I would try something like this:
curl -sku "${jssAPIUsername}:${jssAPIPassword}" "${jssAddress}/JSSResource/mobiledevicecommands/command/RestartDevice/id/"$devices -X POST
Posted on 03-10-2019 10:09 AM
@maxbedford, I haven't fully vetted your command, but try setting your XML data to something like the following:
<mobile_device_command>
<general>
<command>RestartDevice</command>
</general>
<mobile_devices>
<mobile_device>
<udid>DBD8086A-C09D-52CF-9C98-FA0E9B9CFB87</udid>
</mobile_device>
<mobile_device>
<udid>EDAE4A5C-0E22-4BB1-BD0B-08BA89916113</udid>
</mobile_device>
<mobile_device>
<udid>63620D2A-DFD1-42DF-9DC4-3FEE808B1C17</udid>
</mobile_device>
</mobile_devices>
</mobile_device_command>
or
<mobile_device_command>
<general>
<command>RestartDevice</command>
</general>
<mobile_devices>
<mobile_device>
<id>247</id>
</mobile_device>
<mobile_device>
<id>358</id>
</mobile_device>
<mobile_device>
<id>400</id>
</mobile_device>
</mobile_devices>
</mobile_device_command>
If you put the pretty XML into a variable such as "THExml", you can use xmllint to flatten it just before you submit to the Jamf Pro Classic API:
flatXML=$( /usr/bin/xmllint --noblanks - <<< "$THExml" )
Posted on 03-10-2019 09:20 PM
Try this @maxbedford
#!/bin/sh
jamfProURL="https://acme.jamfcloud.com"
jamfUser=""
jamfPass=""
mobileDeviceGroupID=""
deviceIDs=( $( curl -k -s -u "$jamfUser":"$jamfPass" $jamfProURL/JSSResource/mobiledevicegroups/id/$mobileDeviceGroupID -H "Accept: application/xml" -X GET | xpath "//mobile_device_group/mobile_devices" | /usr/bin/perl -lne 'BEGIN{undef $/} while (/<id>(.*?)</id>/sg){print $1}' ) )
for i in ${deviceIDs[@]}; do
echo "Sending Restart Command to Device ID: $i..."
/usr/bin/curl -sk -u "$jamfUser":"$jamfPass" -H "Content-Type: text/xml" -d "<?xml version="1.0" encoding="ISO-8859-1"?><mobile_device_command><general><command>RestartDevice</command>></general><mobile_devices><mobile_device><id>$i</id></mobile_device></mobile_devices></mobile_device_command>" $jamfProURL/JSSResource/mobiledevicecommands/command/RestartDevice -X POST > /dev/null
if [[ "$?" == "0" ]]; then
echo " Command Processed Successfully"
else
echo " Error Processing Command"
fi
echo ""
done
exit 0
Posted on 03-13-2019 11:09 AM
@cdenesha Thanks %2C is the ASCII code for a comma and somewhere I had seen reports of using that instead of a comma to fix issues.
@talkingmoose Thanks I tried a couple of different ways. At this point, I'm thinking about the solution that requires minimal parsing. It is good to know what XML format works.
@yoopersteeze Thanks! A lot of good pieces in there. I don't really want to bring Perl into this ATM.
I got it working and tested. Looking at using it to force iOS updates to our student population. That is the next step.
Posted on 03-13-2019 12:52 PM
This does assume that the iPad is being used at the time that the command gets sent? Otherwise if the iPad is sleeping in a cart or locker or something, when the user turns it on next it will just immediately restart.
Posted on 03-15-2019 04:22 AM
At no point in time have I made any statements on the assumption of the current state of the iPad,
I do understand that the iPad doesn't get the command immediately and that they get them when the iPad wakes back up, which as you point out maybe when the user next turns it on, it also maybe 2 minutes into a user waking up the iPad.