Why are the values in my Jamf parameters not being passed?

howie_isaacks
Valued Contributor III

I created a script that prompts users to run the latest macOS update. The script works perfectly when run through a policy, so there are no issues with the overal functionality of the script. The policy is scoped only to Macs that are not yet running macOS 15.4. We have not decided to allow updates to 15.4.1 just yet. I noticed that the policy ran on a Mac running macOS 15.4. It's likely that this Mac had not yet ran a current inventory that would have put it in the macOS 15.4 smart group, which would have excluded it from running the policy. I decided to add a function to the script to check the current installed macOS and then compare it to the required macOS version. If the Mac is already running 15.4 or higher, I want the script to exit without doing anything. The idea is to run this function before doing anything else. If I fill in "15" for "reqosMajor" and "4" for "reqosMinor", this works perfectly. I put this function into a script by itself to test. Each time the function runs using parameters 8 and 9, the values for the two variables expand to nothing. If the values are filled in, the values for the variables work later on in the script when it checks if the required major and minor versions are greater than or equal to the current installed major and minor versions. I used set -x and I can see that the values entered into the parameters are not being passed. I have used parameters in this way for a long time. I don't understand why this is not working. I also tried using parameters 4 and 5. That doesn't work either. What am I doing wrong? Most of my scripts are zsh. I also tried switching to using bash. It had no effect.

 

macOSVersionCheck() {
	
	# Define variables
	local osMajor
	local osMinor
	local reqosMajor
	local reqosMinor
	local macOSVersion
	
	macOSVersion=$(/usr/bin/sw_vers | grep "ProductVersion" | /usr/bin/awk '{ print $2 }')
	osMajor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}')
	osMinor=$(/usr/bin/sw_vers -productVersion | awk -F . '{print $2}')
	reqosMajor="$8" # Parameter 8
	reqosMinor="$9"  # Parameter 9
	reqOS="${reqosMajor}.${reqosMinor}"
	
	echo "Required macOS version is ${reqOS}"
	echo "Current installed macOS version is $macOSVersion"
	
	if [ "$osMajor" -ge "$reqosMajor" ] && [ "$osMinor" -ge "$reqosMinor" ]; then
		echo "The current installed macOS version is greater than or equal to the required version. No update needed."
		# Stop here. No update is needed.
		exit 0
	else
		echo "The current installed macOS version is less than the required version. Update is needed."
	fi
}

 

1 ACCEPTED SOLUTION

sdagley
Esteemed Contributor III

Expressed another way, the $N (e.g. $1, $2,...) parameters in your script and in a function defined in your script are not the same parameters so your macOSVersionCheck function had no idea what the values for $8 and $9 which were passed into your script are because they represent the 8th and 9th parameters passed when calling the macOSVersionCheck.

Calling macOSVersionCheck with $@ as a parameter tells the shell to pass all the arguments that were passed to your script when it was called.

Here's a script to demonstrate:

#!/bin/zsh

testFunction() {
	echo "In testFunction"
	echo "Parameter 2: $2"
	echo "Parameter 3: $3"
	echo "Parameter 4: $4"
}

echo "In Body"
echo "Parameter 2: $2"
echo "Parameter 3: $3"
echo "Parameter 4: $4"

echo "Calling test function with no prarameters"
testFunction

echo "Calling test function with the \$@ parameter"
testFunction $@

Save it to disk as ParameterDemo.sh, then run it in Terminal like this:

/Path/To/Scripts/ParameterDemo.sh "Parameter 1" "Parameter 2" "Parameter 3", "Parameter 4"

That should produce the following output:

In Body
Parameter 2: Parameter 2
Parameter 3: Parameter 3
Parameter 4: Parameter 4
Calling test function with no prarameters
In testFunction
Parameter 2:
Parameter 3:
Parameter 4:
Calling test function with the $@ parameter
In testFunction
Parameter 2: Parameter 2
Parameter 3: Parameter 3
Parameter 4: Parameter 4

 

View solution in original post

7 REPLIES 7

sdagley
Esteemed Contributor III

@howie_isaacks The $n parameters inside a function represent the parameters passed to the function, not the parameters passed to the script. If you want to pass all of the parameters passed to your script to a function in your script call the function with the parameter $@ like this:

macOSVersionCheck $@

 

howie_isaacks
Valued Contributor III

Thanks for your help! Maybe I don't understand what you said to do but I added "$@" as you wrote. I have set -x at the beginning of the script so I can see all the commands running.  I added in two lines to echo the values in parameters 8 and 9 to see if those values show up. This is what I see:

Running script macOS Version Check Test...

Script exit code: 0

Script result: +/Library/Application Support/JAMF/tmp/macOS Version Check Test:36> macOSVersionCheck / QXJ0PWLY2C HIsaacksJ 15 4

+macOSVersionCheck:3> local osMajor

+macOSVersionCheck:4> local osMinor

+macOSVersionCheck:5> local reqosMajor

+macOSVersionCheck:6> local reqosMinor

+macOSVersionCheck:7> local macOSVersion

+macOSVersionCheck:9> macOSVersion=+macOSVersionCheck:9> /usr/bin/sw_vers

+macOSVersionCheck:9> macOSVersion=+macOSVersionCheck:9> grep ProductVersion

+macOSVersionCheck:9> macOSVersion=+macOSVersionCheck:9> /usr/bin/awk '{ print $2 }'

+macOSVersionCheck:9> macOSVersion=15.4.1 

+macOSVersionCheck:10> osMajor=+macOSVersionCheck:10> /usr/bin/sw_vers -productVersion

+macOSVersionCheck:10> osMajor=+macOSVersionCheck:10> awk -F . '{print $1}'

+macOSVersionCheck:10> osMajor=15 

+macOSVersionCheck:11> osMinor=+macOSVersionCheck:11> /usr/bin/sw_vers -productVersion

+macOSVersionCheck:11> osMinor=+macOSVersionCheck:11> awk -F . '{print $2}'

+macOSVersionCheck:11> osMinor=4 

+macOSVersionCheck:12> reqosMajor='' 

+macOSVersionCheck:13> reqosMinor='' 

+macOSVersionCheck:14> reqOS=. 

+macOSVersionCheck:16> echo 'Parameter 8 is '

Parameter 8 is 

+macOSVersionCheck:17> echo 'Parameter 9 is '

Parameter 9 is 

+macOSVersionCheck:19> echo 'Required macOS version is .'

Required macOS version is .

+macOSVersionCheck:20> echo 'Current installed macOS version is 15.4.1'

Current installed macOS version is 15.4.1

+macOSVersionCheck:22> [ 15 -ge '' ']'

+macOSVersionCheck:22> [ 4 -ge '' ']'

+macOSVersionCheck:23> echo 'The current installed macOS version is greater than or equal to the required version. No update needed.'

The current installed macOS version is greater than or equal to the required version. No update needed.

+macOSVersionCheck:25> exit 0

sdagley
Esteemed Contributor III

Expressed another way, the $N (e.g. $1, $2,...) parameters in your script and in a function defined in your script are not the same parameters so your macOSVersionCheck function had no idea what the values for $8 and $9 which were passed into your script are because they represent the 8th and 9th parameters passed when calling the macOSVersionCheck.

Calling macOSVersionCheck with $@ as a parameter tells the shell to pass all the arguments that were passed to your script when it was called.

Here's a script to demonstrate:

#!/bin/zsh

testFunction() {
	echo "In testFunction"
	echo "Parameter 2: $2"
	echo "Parameter 3: $3"
	echo "Parameter 4: $4"
}

echo "In Body"
echo "Parameter 2: $2"
echo "Parameter 3: $3"
echo "Parameter 4: $4"

echo "Calling test function with no prarameters"
testFunction

echo "Calling test function with the \$@ parameter"
testFunction $@

Save it to disk as ParameterDemo.sh, then run it in Terminal like this:

/Path/To/Scripts/ParameterDemo.sh "Parameter 1" "Parameter 2" "Parameter 3", "Parameter 4"

That should produce the following output:

In Body
Parameter 2: Parameter 2
Parameter 3: Parameter 3
Parameter 4: Parameter 4
Calling test function with no prarameters
In testFunction
Parameter 2:
Parameter 3:
Parameter 4:
Calling test function with the $@ parameter
In testFunction
Parameter 2: Parameter 2
Parameter 3: Parameter 3
Parameter 4: Parameter 4

 

howie_isaacks
Valued Contributor III

I'm accepting this as the solution because you got me to rethink this whole thing. Note that I was defining these variables as local to the function. Apparently that doesn't work with Jamf parameters. I use local variables in functions when I know I need to keep the logic inside the function but in this case, I don't. I placed reqosMajor and reqosMinor outside of the function and they worked exactly as I need them to.

sdagley
Esteemed Contributor III

reqosMajor and reqosMinor being function local variables is irrelevant. The reason that reqosMajor and reqosMinor did not work inside the function without passing $@ as a parameter is because you were assigning them to the 8th and 9th parameters passed into the function, not those parameters passed to the parent script. Simply calling macOSVersionCheck with no parameters resulted in reqosMajor and reqosMinor being unassigned/empty because there were nothing to assign them to. By setting them outside the function the assignment worked because you were now referencing the 8th and 9th parameters passed into the script.

howie_isaacks
Valued Contributor III

Thanks! I will continue trying this out. I appreciate your help and advice. You have been mentioned in the notes in a lot of my scripts since you've provided so much help over the years.

sdagley
Esteemed Contributor III

We all learn sometime :-) Many years ago in the early days of Macs I called the publisher of Consulair Mac C to ask why the program I was trying to convert from Pascal to C kept crashing. Bill kindly explained the difference in how Pascal and C differentiated when incrementing a pointer, and then recommended a book on C programming I should read.