16

How come the following, i.e. echoing $PATH directly from bash -c:

docker exec -i -t my_container bash -c "echo $PATH"

returns a different value for $PATH than what follows, i.e. starting an interactive bash session and echoing the $PATH?

docker exec -i -t my_container bash 
root@21e6d898c3c2:/# echo $PATH

To give some context to this question, I'd like to run a command in the container with docker exec, and this command is on the path if I start an interactive bash session, but isn't if I just run the command.

Using the full path of the executable isn't a workaround in this case, as the command relies on other environment variables that, just like PATH are set in a bash interactive session, but not if I run the command up straight.

1
  • 1
    In addition to what @chicks pointed out, using docker ... "echo $PATH" will substitute your PATH before it starts docker, let alone the bash shell. If you want to see the PATH of the shell running under docker, use single-quotes (docker ... 'echo $PATH') to prevent premature evaluation of the PATH variable. – Gordon Davisson Nov 25 '16 at 3:30
6

When -c is specified bash is not running as interactive or a login shell so it won't read the same startup scripts. Anything set in /etc/profile, ~/.bash_profile, ~/.bash_login, or ~/.profile would definitely be skipped.

Also, as explained by the bash man page:

Bash attempts to determine when it is being run with its standard input connected to a network connection, as when executed by the remote shell daemon, usually rshd, or the secure shell daemon sshd. If bash determines it is being run in this fashion, it reads and executes commands from ~/.bashrc and ~/.bashrc, if these files exist and are readable.

So if it doesn't think you're connecting across the network it might not read the .bashrc file either which would skip everything not skipped by the previous step.

solution

To work around this issue I would create a script that sets the PATH to something suitable and then run the command. If you want to use the existing .profile or other files then you can just source it in your script.

1
  • 5
    why not run with bash -l -c "command" – Max Ivak Nov 22 '17 at 21:23
8

In your first example:

docker exec -i -t my_container bash -c "echo $PATH"

That will evaluate the $PATH variable with your shell on your docker client, outside of the container, and then pass the expanded value as the command to run inside the container. You can compare the value of the above to running echo $PATH on the command line outside of docker and see that they are the same.

In your second example:

docker exec -i -t my_container bash 
root@21e6d898c3c2:/# echo $PATH

That will evaluate the $PATH variable inside the container.

You can escape your first example, or single quote it to prevent the bash shell on your workstation from expanding it, so that it is evaluated inside the container. Either of the following would work:

docker exec -i -t my_container bash -c "echo \$PATH"
docker exec -i -t my_container bash -c 'echo $PATH'
1
  • 1
    Or ... bash -c "printenv PATH" or ... bash -c "declare -p PATH" which pass only the name PATH (not its value) and let the program or shell inside the container do the lookup – dave_thompson_085 May 10 '19 at 3:48
4

Try the -l option for bash. It will run in login shell and load /etc/profile.

docker exec -i -t my_container bash -lc "echo $PATH"
1
  • Inside double quotes the $PATH here is evaluated by your shell outside the container, not the shell inside the container. See the BMitch answer. – Mnebuerquo Feb 20 at 15:16

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.