Shell – Environment variable for command called via nice

environment-variablesniceshell

I need to set an environment variable for a command that is being called via nice. [Bash and dash, Slackware and FreeBSD.]

 $ JIM=20 nice -n 10 echo $JIM

 $

Nope, echo can't see JIM

 $ nice -n 10 JIM=20 echo $JIM
 nice: JIM=20: No such file or directory
 $

nice don't like it.

I can export JIM and then echo can see it, but now I'm polluting the environment. Unclean!

I tried the "–" option to signify end of command line variables for nice, but it makes no difference, nice complains. I can't believe no one has wanted to do this before, so I'm probably making a very basic error.

Any ideas?

Best Answer

JIM=x
JIM=20 nice -n 10 echo $JIM

does pass the JIM=20 environment variable to nice, but it's not nice nor echo that expands $JIM, that's the shell.

The shell forks a process and executes:

execve("/usr/bin/nice", ["nice", "-n", "10", "echo", "x"], ["JIM=20", other vars])

nice sets the niceness and then executes in the same process:

execve("/bin/echo", ["echo", "x"], ["JIM=20", other vars])

So echo does receive JIM=20 in its environment, but echo doesn't do anything with its environment.

Had you run:

JIM=20 nice -n 10 sh -c 'echo $JIM'

Then sh would have done something with that environment variable. Shells map the environment variables they receive to shell variables. So above, that sh would have set its $JIM variable to 20 and called its echo builtin with 20 as argument.

Related Question