passing output from one script to another

ChrisJScott
New Contributor III

I'm trying to do something where I have ScriptA populate a variable (we'll call it variable01) and then I'd like to subsequently pass that variable on to ScriptB.

In ScriptA, I'm populating the variable and then exporting it (under the assumption that it will remain in the session and be available when ScriptB executes).

In ScriptB, I refer to the variable as $4, as...

In the policy, I have ScriptA executing first and then ScriptB and, in the ScriptB parameters, I've entered $variable01 as parameter #4.

Obviously: it isn't working. Any ideas on how I can get this to fly?

10 REPLIES 10

bpavlov
Honored Contributor

Can you be more specific? Often, when this has come up, it's determined that all of this could be done in one script and multiple scripts are not required. What exactly is script A doing? What is script B doing?

Worst case, write out value to a file on the drive and have Script B read from that to pick up variable value.

ChrisJScott
New Contributor III

ScriptA is prompting user for the computer's office location (list of cities). It then runs a curl command to assign that system to the appropriate JAMF site.

ScriptB is one that renames the computer based on that city choice, but it's not using the full name but, rather a two-character abbreviation. ScriptA assigns the appropriate two-letter abbreviation to shortCity and I want to pass that on to ScriptB.

Why do it this way? Because I'd like to keep scripts to one function each - the renaming script can/should be able to be utilized by itself and this "daisy chaining" I'm trying to do is an effort to not have t prompt the user multiple times for, basically, the same info.

I have a sneaking suspicion that storing the alue as a tect file and then pulling it in in ScriptB may be the only way to go, but I figured it was worth exploring.

What do you think?

bpavlov
Honored Contributor

I think just like I mentioned, there's not a very good reason to separate this out. There's no reason the user needs to be prompted multiple times for the same info. Just build your script in such a fashion that it prompts only when it needs to. If you're on Slack http://macadmins.org, I'm sure you'd get some good suggestions depending on what language you're scripting in. They got channels for almost all languages (Bash, Python, AppleScript, Swift, etc.) You can definitely do this in one script. Don't be afraid to make your script longer. And if you're concerned with things getting complicated, start using functions so that code can be made repeatable, and the script itself is more adaptable/flexible.

tlarkin
Honored Contributor

There are many ways to do this but it just depends on how you want to do it.

with in your script you can do something like this

myvar ='foo'

/path/to/interpreter myscript $myvar

I do not really quite understand what you are trying to build here and also be aware that if you use the jamf binary to call a script it will pass all the parameters and 1, 2 and 3 are reserved, but from the command line it still lists them as 1, 2 and 3. From the help doc:

Usage:   jamf runScript -script <file name> -path <path to script> [-computerName <computerName>]
         [-target <target volume>] [-username <username>] [-p1 <parameter 1>] [-p2 <parameter 2>] 
         [-p3 <parameter 3>] [-p4 <parameter 4>] [-p5 <parameter 5>] [-p6 <parameter 6>] 
         [-p7 <parameter 7>] [-p8 <parameter 8>] 


     -script         The file name of the script to run

     -path           The path to the script

     -computerName       The name of the computer to be passed to the script
                 If the name is not specified, it will be looked up on the target drive.

     -target         The target drive to be passed to the script

     -username       The username to be passed to the script

     -p[1-8]         The parameters to be passed to the script


Notes:   Parameters in scripts created for use with the Casper Suite must be 
     formatted in a certain way. The parameters passed to the script are as follows:
         Target Drive 
         Computer Name 
         Username 
         Parameter 1 
         Parameter 2 
         Parameter 3 
         Parameter 4 
         Parameter 5 
         Parameter 6 
         Parameter 7 
         Parameter 8

mm2270
Legendary Contributor III

I'm also not clear why these are being split up into 2 different scripts. It seems to me that the script can prompt for the input and then pass the user response to a function within the same script that would get the appropriate abbreviation (maybe using a case statement) and then name the device, if I'm understanding the general idea of what you're looking to do. All of that should be completely possible in one script and still be flexible enough.

As you mentioned, you could pipe the variable captured into a file and have that picked up by the next script, but honestly, that seems overly complicated. I think you're making this too hard on yourself really.

ChrisJScott
New Contributor III

I appreciate everybody's input. Really, I'm trying this as an intellectual exercise - I don't HAVE to do it this way but I'm interested to figure out if I CAN do it this way (!).

Part of it is the "modular mentality" in my brain - ScriptB is a function that can also be used by the end user via Self Service (in addition to being used during initial enrollment), so why have the same code in two different places (as a standalone for SS usage and as part of a longer, multipurpose script for DEP)?

ChrisJScott
New Contributor III

As a follow-up, I don't think EXPORTing the variable from within ScriptA so that it's available when ScriptB runs will work because exported variables only persist for a single session and I think/suspect that JAMF runs each policy as a separate session.

mm2270
Legendary Contributor III

Yeah, I believe your suspicion on that is correct. Each script has its own environment and it won't pick up variables defined or exported in other scripts previously.

Other than piping the string into a file to read in ScriptB, the only other way I know to do this would be to have ScriptB run ScriptA itself and capture the output from an echo or printf command. IOW, if ScriptB could do something like:

variable01=$(sh /path/to/ScriptA.sh)

in it, and ScriptA had a line near the end that did a echo $variable01, then within ScriptB it would populate the variable01 string with the output from ScriptA.

But of course from the standpoint of a policy running out of Jamf Pro, this wouldn't be so easy. You could possibly do it with the API. I know how to grab script contents using API calls and pull them down into a local file, make them usable (they default to using web encoded strings), make it executable and then run it. That would mean ScriptA could still live independently within your JSS (JPS?) and ScriptB could still utilize it without making it embedded within itself.

Does that make sense? :)

tlarkin
Honored Contributor
I appreciate everybody's input. Really, I'm trying this as an intellectual exercise - I don't HAVE to do it this way but I'm interested to figure out if I CAN do it this way (!). Part of it is the "modular mentality" in my brain - ScriptB is a function that can also be used by the end user via Self Service (in addition to being used during initial enrollment), so why have the same code in two different places (as a standalone for SS usage and as part of a longer, multipurpose script for DEP)?

@ChrisJScott

What language are you wanting to write the code in?

kendalljjohnson
Contributor II

I'm not sure if it is the "correct" way to do it but a while back I had a scenario where my scriptA captures a user's input for variables in order to mount an SMB and then scriptB runs various tasks like making a disk image to the SMB, that is then outputted to a log that will be stored on the SMB.

At the end of scriptA I use the following command to pass the variables set in scriptA and then trigger scriptB while logging the output.

. /path/to/scriptB "$variable" "$variable2" "$variable3" "$variable4" > >(tee -a /path/to/SMB/log.log) 2> >(tee -a /path/to/SMB/log.log >&2)

scriptB then starts with doing an echo of each variable within the log to confirm everything transfers over.