3

Is there a way to pass an environment variable to two processes that are started in one line in bash? I want to execute two processes in the same command line

# these are ways to execute two processes in the same line
exec1 & exec2
exec1 && exec2
exec1 || exec2
exec1; exec2

And this is the way to pass an environment variable to a process:

VAR=value exec

How can I combine both?

# this is not enough because exec2 does not see VAR
VAR=value exec1 & exec2

I know the way to do it with export:

export VAR=value; exec1 & exec2; unset EXPORT

Is there another way to do it without export?

2
  • 1
    Not unless you wrap the two commands in a function. Pre-command environment changes only work for simple commands. Commented Nov 4, 2015 at 17:40
  • 1
    Also, note that your workaround is not equivalent; if VAR had a value before, it no longer does after. Commented Nov 4, 2015 at 18:18

2 Answers 2

2

Yes, you can do this: Scope the export to a subshell. (If you then exec one of the processes from the subshell, you're not taking an efficiency loss in the branch where that line is reached since the fork used to spawn the subshell is the same one that would otherwise be going to run the subprocess). Thus:

(export VAR=value; exec1 & exec exec2)
(export VAR=value; exec1 && exec exec2)
(export VAR=value; exec1 || exec exec2)
(export VAR=value; exec1; exec exec2)

Obviously this is going to have undesired side effects if either of your commands were not actually external but were a shell builtin.


However, my advice? Don't. This makes your code less readable for very, very little gain. Repeating yourself isn't the end of the world in this case.

Sign up to request clarification or add additional context in comments.

9 Comments

Forking to a subprocess can also lead to unexpected results. For example, an exit in a subprocess only stops that subprocess, not the main script. Additionally, extracting return codes from a subprocess can be challenging.
@Mr.Llama, that's covered in the "undesired side effects if either of your commands were not actually external" caveat; exit, after all, being a builtin.
@Mr.Llama, ...as for return codes, the subprocess exits with exit status of the last command it ran -- and when exec is used, of course, the command's exit status is passed through directly; the only case that's going to be trouble here is that where a component was backgrounded.
@CharlesDuffy In my case I want to create an alias in my .bashrc for a command that I often have to repeat and it is complex. If I were to use it in a script the solution would be trivial to split in in more lines of code.
Using shell functions is better practice than aliases regardless -- much more powerful, as they can actually do conditional logic based on arguments -- and moreover, they prevent you from having code-length concerns.
|
1

This may get messy with quoting hell: group the commands to call in a subshell

VAR=value sh -c 'exec1 & exec2'

3 Comments

This is significantly less efficient than the subshell approach, since it's execing a new shell instance -- and to what end? (Also, it means you can't access any non-exported variables in forming your commands, unless expanding them into code and thus introducing eval-equivalent security risk).
I would argue with "significant" (what's really the cost of spawning sh). However, this answer is not largely different from yours.
If you're doing it in an inner loop, the cost of spawning sh adds up very quickly. (Then again, one would want to avoid forks there too -- and use of external commands).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.