1
  1. When a shell runs an external executable as a command, we can pass environment variables into the executable.

    $ var=3 /bin/echo `$var` $ var=3 bash -c "/bin/echo '$var'" 

    both don't output anything.

  2. When a program is executed by exec, I want to see if environment variable also works:

    $ bash $ unset var; $ var=3 exec /bin/echo '$var' $var $ exec var=3 /bin/echo '$var' bash: exec: var=3: not found 

To prevent variable expansion, I use single quote around $var. The protection seems a little too much.

Why is this environment variable not set up in the above cases?

Can I make environment variables work for a program executed by exec?

Thanks.

2 Answers 2

5

Remember that parameter expansion doesn’t happen magically, you need a shell to do it for you.

var=3 /bin/echo `$var` 

I’m not sure what you’re trying to do with that one, back-ticks aren’t appropriate here (they execute a command and are replaced with its output).

var=3 bash -c "/bin/echo '$var'" 

doesn’t work because parameter expansion occurs before the assignment, so the current shell changes "/bin/echo '$var'" to /bin/echo '' (assuming var is undefined), and the child shell is run with

/bin/echo '' 

Try

var=3 bash -c 'echo $var' 

instead: the single quotes here protect the argument from the current shell, and the new shell is run with

echo $var 

which it will process as you’d expect.

In your second point, my initial comment still applies. If you want to play around with the environment and see what happens, run env and filter its output instead:

var=3 env | grep var var=3 exec env | grep var 
5
  • Thanks. i noticed something perhaps incorrect. and changed it. Commented Aug 8, 2017 at 17:38
  • @Tim could you explain your change? I think it’s wrong... Commented Aug 8, 2017 at 17:39
  • When a shell sees var=3 bash -c "/bin/echo '$var'", the single quotes within the double quotes are literal, so don't prevent parameter expansion $var in the shell, where var is unset. So the child shell which the shell forks to execute the double quoted content sees /bin/echo ''. See Arrow's answer. Commented Aug 8, 2017 at 17:44
  • Still not correct. the current shell changes "/bin/echo '$var'" to /bin/echo '' (assuming var is undefined). parameter expansion happens before quote removal. Commented Aug 8, 2017 at 18:59
  • @Tim huh, yes, that’s what I meant to write :-/. Commented Aug 8, 2017 at 19:46
3
  • All your problems are related to quoting, not environment.

    1. Environment for a command.

      When a shell runs an external executable as a command, we can pass environment variables into the executable.

    Yes, that's a way to set environment variables for a command, external or otherwise.

    But what you are missing in this line[a]:

    $ var=3 /bin/echo "$var" 

    Is that the shell expands the variable when building the arguments, and, if the variable var is not set in the shell which starts the command, this is what is actually executed:

    $ var=3 /bin/echo "" 

    To actually see the present shell expansion, run this:

    $ var=RunningShell ; var=3 /bin/echo "$var" RunningShell 

    One (often times insecure) way to delay the evaluation of the variable is:

    $ var=3 eval /bin/echo '"$var"' 3 

    On the second example you have the quotes exchanged:

    $ var=3 bash -c "/bin/echo '$var'" 

    Prints nothing as the actual command line becomes:

    $ var=3 bash -c "/bin/echo ''" 

    As the value of the (unset) variable $var is expanded. You probably meant this:

    $ var=thisis3 bash -c '/bin/echo "$var"' thisis3 

    In which case the single quotes prevent the expansion of the variable by the executing shell, leaving the expansion to the executed shell (bash -c).

    • Use env to actually see the environment.

      1. When a program is executed by exec, I want to see if environment variable also works:

    Do not exec in your present shell as it will close the running shell.
    You may do this to avoid closing the running shell:

    $ var=3 exec /bin/echo \$var | cat $var 

    As the closed shell will be the one that would be closed anyway, the first sub-shell of a pipe.

    But that will not show you the value of var in the environment. To see variables in the environment, use the command to see the environment:

    $ var=3 env | grep var var=3 

[a] The command you wrote had backquotes `, changing them to single quotes will avoid the expansion of the variable and will print $var.:

$ var=3 /bin/echo '$var' $var 
1
  • Thanks. I am stuck at two examples in our discussion unix.stackexchange.com/q/384801. How would you understand them? Thanks. Commented Aug 8, 2017 at 19:16

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.