1

I have a large configuration script (bash) that is pretty well modularized into separate functions to complete a bunch of tasks for installing/configuring a new rollout of a software suite.

We have realized that it would be very useful to have some of these functions available to be called without executing the entire script. I could have made the script accept an argument to call the specific function, but because the script has grown to well over 1200 lines already, for readability I intend to split it into sub-scripts that will execute from the parent. The goal is that the sub-scripts could execute independently to re-configure something specific.

The parent script (call it the wizard) in its original form, had several global variables that were manipulated by the functions as the script ran. In order for the script to be split, I'm creating a persistent file for all the config values, along with a function that allows functions to update the key=value pairs in the persist file (or adds them, if they don't already exist).

Ok, so the actual question! Since the wizard is the parent script, and the children (sub-scripts) can edit or add config values when they are called, is it acceptable for the wizard to re-source the persist file multiple times through the wizard's flow (which is necessary since sourcing doesn't flow "upwards")? I.e.- any time a wizard function starts that configures a certain piece of software, it sources the file first in case a sub-script made a change to a config value.

Since the functions are sourcing the file, I'm assuming that once the function is complete, it goes out of scope (or whatever the equivalent terminology is in bash). So this shouldn't cause issues, but I'd love to be sure. Thanks for any advice!

**EDIT: For clarification, the main reason for using the persist file (and why I call it that) is that I want it to stay available for when one of the sub-scripts are called on an individual basis. Without the wizard setting up the global variables, they would be missing vital information about their environments when run standalone.

  • 2
    What do you mean by "goes out of scope"? Changes to global variables don't have scope in bash. – choroba Jul 20 '16 at 15:54
  • Since the variables are now needing to be shared across different scripts, I've moved all of the global variables into the persist file. So any functions/scripts that need to use the variables will now source that file (rather than having to keep track of which variables get passed back and forth). – MerrillFraz Jul 20 '16 at 17:35
  • 1
    Perhaps you should think in terms of processes. You have only 1 process, your wizard. When it sources files in order to define new functions, this is still the one same process. When you call those functions, this is still the one same process. So any global variables changed by the functions will be the same ones your wizard knows about. There is no apparent need for a persistent file unless your wizard exits and you want to run it again and recover those old values. – meuh Jul 20 '16 at 17:50
  • Why don't you source your modules scripts when you call them from the main script, global variable would stay in the scope of the main script. You would avoid to maintain a persistent file. – Emmanuel Jul 20 '16 at 18:15
  • 1
    Perhaps you should try to use an sqllite db to store the values, that would made modification and deletion of configuration parameter and locking easier . Squllite provides a command line interface, sqlite3, that can be scripted. I found sqllite installed on almost all Linuxes so you should not have to deploy it as a requisit. – Emmanuel Jul 21 '16 at 8:39
2

Choose one (or more) of the variables that MUST exist for the functions to work and use something like:

[ -z "$REQUIREDVARIABLE" ] && . persistent-file

or

[ -z "$REQ1" ] || [ -z "$REQ2" ] || [ -z "$REQ3" ] && . persistent-file

That way the sourced scripts will only read the persistent file if the variable(s) aren't already in the environment (which they will be, and kept up-to-date, when sourced from the "wizard" script).


PS: IMO you should use your unix/linux's packaging tools for rolling out production code, rather than re-inventing the wheel. If distributing to 3rd-parties, then package for all unixes/linux-distros that you intend to support. Use VMs running specific operating systems and versions to build packages on. And if your code is open source then various distros etc will maintain their own packages or ports if it seems useful or interesting to one of the devs.

  • I'm using yum and standard packaged RPMs (Scientific Linux environment). The wizard is for installing and configuring the correct packages for the specific environments they are being deployed in per customer requirements. And since that is an ever-changing thing, packaging it per-site is not practical or sustainable. – MerrillFraz Jul 21 '16 at 14:20
  • puppet or ansible no use to you? pushing a custom puppet/ansible config to the client hosts seems a lot easier than rewriting much of what they do. – cas Jul 21 '16 at 14:42
  • I have not researched those options, thanks for the heads-up! (I'm the junior engineer, got roped into being the de facto Sys Admin, so it's trial by fire!). – MerrillFraz Jul 21 '16 at 15:04
  • btw, one thing i meant to mention but forgot was that when your scripts write to the persistent file, they should avoid simultaneous writes by using a lockfile. See also the Related links on the RHS of the page. – cas Jul 21 '16 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.