2

The following alternatives exist for passing parameters to an executable under a Bash shell. I believe the first method is more common at present.

method 1 -- pass variables as command line arguments

./myprogram --arg1 1

method 2 -- pass parameters as per-invocation environment variables

arg1=1 ./myprogram

What problems may arise when using the second method?

This closely related question (Argument passing strategy - environment variables vs. command line) is addressing a more broad use of environment variables rather than the direct per-invocation usage that I am interested in.

Community
  • 1
  • 1
Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • 2
    No problems, really. The two aren't interchangeable; your script has to be written correctly to accept either. The only downside of an environment variable compared to a command-line option is that you can set the environment variable in your shell and forget about it. Your program won't know or care how it got set, and you might scratch your head when `./myprogram` unexpectedly works the same as `arg1=1 ./myprogram`. It's harder to accidentally add a command-line option to an invocation. – chepner Aug 17 '16 at 20:27

1 Answers1

3

The first method is more common so easier for others to understand.

In most cases that an environment variable is used ($ORACLE_HOME, $JAVA, ..) it is not set in the commandline but some time before and used by different scripts. So when you think your var should be part of the configuration, using an environment variable (as a default value) is fine.
In other cases I would use parameters.

How about modifing a script:

# First script calling myprogram that uses ...
# Difficult to see, the vars name and lastname
name="John"
while read -r lastname; do
   ./myprogram 
done  < lastnames.txt

Now somebody else wants to change the loop and get all users with the environment variable username from the database.

name="John"
while read -r lastname; do
   ./myprogram 
   username="${lastname}" ~/bin/getdbusers
done  < lastnames.txt

This time you were lucky, the second person also uses the var username and is unaware of the fact that ./myprogram uses lastname. He is tempted to introduce a bug by changing the loop variable:

name="John"
while read -r username; do
   ./myprogram # Oops, this should have been changed into lastname=username ./myprogam
   ~/bin/getdbusers
   ~/bin/somethingWithUserName
done  < lastnames.txt

It s getting harder to understand which programs use $name and other vars.
Using parameters will make it easier to understand and bugs kept away:

name="John"
while read -r lastname; do
   ./myprogram "${name}" "${lastname}"
   ~/bin/getdbusers "${lastname}"
   ~/bin/somethingWithUserName "${lastname}"
done  < lastnames.txt
Walter A
  • 19,067
  • 2
  • 23
  • 43
  • 1
    +1 Good notes on using environment variables in general, but I was specifically asking about the explicit per-invocation usage form, where I think it will be harder to introduce the types of bugs that you are warning against. I can see the temptation to use variables implicitly like you describe. But in order for these snippets to work they probably also require an `export` statement, which may make it a bit less tempting to cheat like this -- or more clear when you do. – Brent Bradburn Aug 17 '16 at 22:04