Skip to main content

Hi All 

Hoping someone can help.

Have found a script for collecting log files using jamf pro API thanks @Travid  @david_maestre for updating the script to work with Jamf pro API I belive its based on this https://github.com/kc9wwh/logCollection which no longer seems to work. I belive due to changes in the API.

Im getting the below errror is there anyway to make it work without needing Xcode, seems to be using some tools which are part of Xcode. My coding skills arent up to much so struggling to find whats bits of Xcode its using as dont appear to be reference in the script.

no developer tools were found at '/Applications/Xcode.app', and no install could be requested (perhaps no UI is present), please install manually from 'developer.apple.com'. Failed to retrieve Jamf Pro Computer ID.



#!/bin/bash ## User Variables jamfProURL="$4" jamfProUser="$5" jamfProPass="$6" logFiles="$7" ## System Variables mySerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}') currentUser=$(stat -f%Su /dev/console) compHostName=$(scutil --get LocalHostName) timeStamp=$(date '+%Y-%m-%d-%H-%M-%S') ## Debugging Outputs (Optional) echo "Jamf Pro URL: $jamfProURL" echo "Jamf Pro User: $jamfProUser" # Do not echo the password for security echo "Log Files: $logFiles" echo "Serial Number: $mySerial" echo "Current User: $currentUser" echo "Computer Hostname: $compHostName" ## Log Collection fileName="$compHostName-$currentUser-$timeStamp.zip" echo "Creating zip file: /private/tmp/$fileName" zip -r /private/tmp/"$fileName" $logFiles ## Obtain API Auth Token authResponse=$(curl -sku "$jamfProUser:$jamfProPass" -X POST "$jamfProURL/api/v1/auth/token") apiAuthToken=$(echo "$authResponse" | plutil -extract token raw -) tokenExpiration=$(echo "$authResponse" | plutil -extract expires raw -) if [ -z "$apiAuthToken" ]; then echo "Failed to obtain API authentication token." echo "Response: $authResponse" exit 1 fi echo "API Authentication Token obtained. Token expires: $tokenExpiration" ## Corrected Filter Field for Serial Number encodedSerial=$(printf '%s' "$mySerial" | python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))') filterQuery="hardware.serialNumber%3D%3D$encodedSerial" ## Get Jamf Pro Computer ID using the Jamf Pro API computerIDResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/computers-inventory?filter=$filterQuery") jamfProID=$(echo "$computerIDResponse" | python3 -c " import sys, json data = json.load(sys.stdin) if data['totalCount'] > 0: print(data['results'][0]['id']) else: sys.exit(1) " 2>/dev/null) if [ -z "$jamfProID" ]; then echo "Failed to retrieve Jamf Pro Computer ID." echo "Response: $computerIDResponse" exit 1 fi echo "Jamf Pro Computer ID: $jamfProID" ## Upload Log File uploadResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" -X POST "$jamfProURL/api/v1/computers-inventory/$jamfProID/attachments" -F file=@/private/tmp/$fileName) echo "Upload Response: $uploadResponse" ## Check for successful upload if [[ "$uploadResponse" == *"id"* ]]; then echo "Log file uploaded successfully." else echo "Failed to upload log file." exit 1 fi ## Invalidate API Auth Token curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/auth/invalidate-token" -X POST ## Cleanup rm /private/tmp/"$fileName" exit 0

 
Thanks

if you wanted to run this device on the end user's machine, Python was removed from macOS long ago, I don't think it will execute.  it gives an error as command line tools are not installed, you can install the same using the command "xcode-select --install" 


Thanks @Shyamsundar  just testing with deploying xcode via vpp apps.

Did try xcode-select --install but prompts the users not sure if there away to install in silently 


@tdenton Where did the python call in that script come from? It is not part of the https://github.com/kc9wwh/logCollection script and isn't necessary to get a Mac's serial number.

And here's an updated version of the log collections script that uses Bearer Token auth since Basic Auth is no longer supported for the API:

#!/bin/bash # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2020 Jamf. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the Jamf nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This script was designed to be used in a Self Service policy to allow the facilitation # or log collection by the end-user and upload the logs to the device record in Jamf Pro # as an attachment. # # REQUIREMENTS: # - Jamf Pro # - macOS Clients running version 10.13 or later # # # For more information, visit https://github.com/kc9wwh/logCollection # # Written by: Joshua Roskos | Jamf # Revised by: Alton Brailovskiy | Martin Cox (Jamf) # # Revision History # 2024-07-23: Updated Script - https://github.com/kc9wwh/logCollection/blob/master/BearerAuth.sh # 2023-11-30: Added support for bearer auth and invalidating bearer token once done. # 2020-12-01: Added support for macOS Big Sur # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## User Variables ## Ensure not to include the / at the end of the JamfProURL parameter. ex https://instance.jamfcloud.com is the parameter NOT https://instance.jamfcloud.com/ ## Suggested Logs to pull: /private/var/log/install.log* /private/var/log/jamf.log* /private/var/log/system.log* jamfProURL="$4" jamfProUser="$5" jamfProPass="$6" logFiles="$7" bearerTokenResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/token" -X POST) if [[ $? -eq 0 ]]; then bearerToken=$(echo "$bearerTokenResponse" | plutil -extract token raw -) echo "Bearer token: $bearerToken" else echo "Authentication failed. Check credentials or endpoint." fi ## System Variables mySerial=$(system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $NF}') currentUser=$( stat -f%Su /dev/console ) compHostName=$( scutil --get LocalHostName ) timeStamp=$( date '+%Y-%m-%d-%H-%M-%S' ) osMajor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') osMinor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $2}') ## Log Collection fileName=$compHostName-$currentUser-$timeStamp.zip zip /private/tmp/$fileName $logFiles ## Upload Log File if [[ "$osMajor" -ge 11 ]]; then jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath -e "//computer/general/id/text()" ) elif [[ "$osMajor" -eq 10 && "$osMinor" -gt 12 ]]; then jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath "//computer/general/id/text()" ) fi curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/fileuploads/computers/id/$jamfProID -F name=@/private/tmp/$fileName -X POST ## Cleanup rm /private/tmp/$fileName # Invalidate the bearer token after file upload invalidateResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/invalidateToken" -X POST -H "Authorization: Bearer $bearerToken") if [[ $? -eq 0 ]]; then echo "Bearer token invalidated successfully." else echo "Failed to invalidate bearer token. Response: $invalidateResponse" fi exit 0

The above looks accurate./ 

I'll attach mine just incase -- currently working just fine. 

Thanks

#!/bin/bash ## User Variables jamfProURL="$4" jamfProUser="$5" jamfProPass="$6" logFiles="$7" ## System Variables mySerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}') currentUser=$(stat -f%Su /dev/console) compHostName=$(scutil --get LocalHostName) timeStamp=$(date '+%Y-%m-%d-%H-%M-%S') ## Debugging Outputs (Optional) echo "Jamf Pro URL: $jamfProURL" echo "Jamf Pro User: $jamfProUser" # Do not echo the password for security echo "Log Files: $logFiles" echo "Serial Number: $mySerial" echo "Current User: $currentUser" echo "Computer Hostname: $compHostName" ## Log Collection fileName="$compHostName-$currentUser-$timeStamp.zip" echo "Creating zip file: /private/tmp/$fileName" zip -r /private/tmp/"$fileName" $logFiles ## Obtain API Auth Token authResponse=$(curl -sku "$jamfProUser:$jamfProPass" -X POST "$jamfProURL/api/v1/auth/token") apiAuthToken=$(echo "$authResponse" | plutil -extract token raw -) tokenExpiration=$(echo "$authResponse" | plutil -extract expires raw -) if [ -z "$apiAuthToken" ]; then echo "Failed to obtain API authentication token." echo "Response: $authResponse" exit 1 fi echo "API Authentication Token obtained. Token expires: $tokenExpiration" ## Corrected Filter Field for Serial Number encodedSerial=$(printf '%s' "$mySerial" | python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))') filterQuery="hardware.serialNumber%3D%3D$encodedSerial" ## Get Jamf Pro Computer ID using the Jamf Pro API computerIDResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/computers-inventory?filter=$filterQuery") jamfProID=$(echo "$computerIDResponse" | python3 -c " import sys, json data = json.load(sys.stdin) if data['totalCount'] > 0: print(data['results'][0]['id']) else: sys.exit(1) " 2>/dev/null) if [ -z "$jamfProID" ]; then echo "Failed to retrieve Jamf Pro Computer ID." echo "Response: $computerIDResponse" exit 1 fi echo "Jamf Pro Computer ID: $jamfProID" ## Upload Log File uploadResponse=$(curl -sk --header "Authorization: Bearer $apiAuthToken" -X POST "$jamfProURL/api/v1/computers-inventory/$jamfProID/attachments" -F file=@/private/tmp/$fileName) echo "Upload Response: $uploadResponse" ## Check for successful upload if [[ "$uploadResponse" == *"id"* ]]; then echo "Log file uploaded successfully." else echo "Failed to upload log file." exit 1 fi ## Invalidate API Auth Token curl -sk --header "Authorization: Bearer $apiAuthToken" "$jamfProURL/api/v1/auth/invalidate-token" -X POST ## Cleanup rm /private/tmp/"$fileName" exit 0

@tdenton Where did the python call in that script come from? It is not part of the https://github.com/kc9wwh/logCollection script and isn't necessary to get a Mac's serial number.

And here's an updated version of the log collections script that uses Bearer Token auth since Basic Auth is no longer supported for the API:

#!/bin/bash # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2020 Jamf. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the Jamf nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This script was designed to be used in a Self Service policy to allow the facilitation # or log collection by the end-user and upload the logs to the device record in Jamf Pro # as an attachment. # # REQUIREMENTS: # - Jamf Pro # - macOS Clients running version 10.13 or later # # # For more information, visit https://github.com/kc9wwh/logCollection # # Written by: Joshua Roskos | Jamf # Revised by: Alton Brailovskiy | Martin Cox (Jamf) # # Revision History # 2024-07-23: Updated Script - https://github.com/kc9wwh/logCollection/blob/master/BearerAuth.sh # 2023-11-30: Added support for bearer auth and invalidating bearer token once done. # 2020-12-01: Added support for macOS Big Sur # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## User Variables ## Ensure not to include the / at the end of the JamfProURL parameter. ex https://instance.jamfcloud.com is the parameter NOT https://instance.jamfcloud.com/ ## Suggested Logs to pull: /private/var/log/install.log* /private/var/log/jamf.log* /private/var/log/system.log* jamfProURL="$4" jamfProUser="$5" jamfProPass="$6" logFiles="$7" bearerTokenResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/token" -X POST) if [[ $? -eq 0 ]]; then bearerToken=$(echo "$bearerTokenResponse" | plutil -extract token raw -) echo "Bearer token: $bearerToken" else echo "Authentication failed. Check credentials or endpoint." fi ## System Variables mySerial=$(system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $NF}') currentUser=$( stat -f%Su /dev/console ) compHostName=$( scutil --get LocalHostName ) timeStamp=$( date '+%Y-%m-%d-%H-%M-%S' ) osMajor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') osMinor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $2}') ## Log Collection fileName=$compHostName-$currentUser-$timeStamp.zip zip /private/tmp/$fileName $logFiles ## Upload Log File if [[ "$osMajor" -ge 11 ]]; then jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath -e "//computer/general/id/text()" ) elif [[ "$osMajor" -eq 10 && "$osMinor" -gt 12 ]]; then jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath "//computer/general/id/text()" ) fi curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/fileuploads/computers/id/$jamfProID -F name=@/private/tmp/$fileName -X POST ## Cleanup rm /private/tmp/$fileName # Invalidate the bearer token after file upload invalidateResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/invalidateToken" -X POST -H "Authorization: Bearer $bearerToken") if [[ $? -eq 0 ]]; then echo "Bearer token invalidated successfully." else echo "Failed to invalidate bearer token. Response: $invalidateResponse" fi exit 0

@sdagley  didnt spot that, thanks so much this is working perfectley.

Thanks also for posting your version @david_maestre 


@tdenton Where did the python call in that script come from? It is not part of the https://github.com/kc9wwh/logCollection script and isn't necessary to get a Mac's serial number.

And here's an updated version of the log collections script that uses Bearer Token auth since Basic Auth is no longer supported for the API:

#!/bin/bash # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2020 Jamf. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the Jamf nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This script was designed to be used in a Self Service policy to allow the facilitation # or log collection by the end-user and upload the logs to the device record in Jamf Pro # as an attachment. # # REQUIREMENTS: # - Jamf Pro # - macOS Clients running version 10.13 or later # # # For more information, visit https://github.com/kc9wwh/logCollection # # Written by: Joshua Roskos | Jamf # Revised by: Alton Brailovskiy | Martin Cox (Jamf) # # Revision History # 2024-07-23: Updated Script - https://github.com/kc9wwh/logCollection/blob/master/BearerAuth.sh # 2023-11-30: Added support for bearer auth and invalidating bearer token once done. # 2020-12-01: Added support for macOS Big Sur # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## User Variables ## Ensure not to include the / at the end of the JamfProURL parameter. ex https://instance.jamfcloud.com is the parameter NOT https://instance.jamfcloud.com/ ## Suggested Logs to pull: /private/var/log/install.log* /private/var/log/jamf.log* /private/var/log/system.log* jamfProURL="$4" jamfProUser="$5" jamfProPass="$6" logFiles="$7" bearerTokenResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/token" -X POST) if [[ $? -eq 0 ]]; then bearerToken=$(echo "$bearerTokenResponse" | plutil -extract token raw -) echo "Bearer token: $bearerToken" else echo "Authentication failed. Check credentials or endpoint." fi ## System Variables mySerial=$(system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $NF}') currentUser=$( stat -f%Su /dev/console ) compHostName=$( scutil --get LocalHostName ) timeStamp=$( date '+%Y-%m-%d-%H-%M-%S' ) osMajor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') osMinor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $2}') ## Log Collection fileName=$compHostName-$currentUser-$timeStamp.zip zip /private/tmp/$fileName $logFiles ## Upload Log File if [[ "$osMajor" -ge 11 ]]; then jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath -e "//computer/general/id/text()" ) elif [[ "$osMajor" -eq 10 && "$osMinor" -gt 12 ]]; then jamfProID=$( curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/computers/serialnumber/$mySerial/subset/general | xpath "//computer/general/id/text()" ) fi curl -k -H "Authorization: Bearer ${bearerToken}" $jamfProURL/JSSResource/fileuploads/computers/id/$jamfProID -F name=@/private/tmp/$fileName -X POST ## Cleanup rm /private/tmp/$fileName # Invalidate the bearer token after file upload invalidateResponse=$(curl -s -u "$jamfProUser":"$jamfProPass" "$jamfProURL/api/v1/auth/invalidateToken" -X POST -H "Authorization: Bearer $bearerToken") if [[ $? -eq 0 ]]; then echo "Bearer token invalidated successfully." else echo "Failed to invalidate bearer token. Response: $invalidateResponse" fi exit 0

I know this is an older post, but thank you for posting a working version @sdagley!