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?

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.


Try this

( export a=20; nice -n 10 sh -c 'echo $a' )
  • This expands the variable in the argument list (which is what the OP's example tries to do), but it doesn't pass it in the environment (which is what the question asks for.)
    – alexis
    Jan 24 '14 at 15:47

For my particular case, I ended up making the script renice itself, similar to this:

JIM=20 sh -c 'renice -n +15 -p $$; echo ${JIM}'

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.