为什么环境变量与`bash -c`不同

Ale*_*net 16 bash docker

怎么会出现以下情况,即$PATH直接从bash -c

docker exec -i -t my_container bash -c "echo $PATH"
Run Code Online (Sandbox Code Playgroud)

返回$PATH与后面不同的值,即启动交互式 bash 会话并回显$PATH?

docker exec -i -t my_container bash 
root@21e6d898c3c2:/# echo $PATH
Run Code Online (Sandbox Code Playgroud)

为了给这个问题提供一些上下文,我想在容器中运行一个命令,docker exec如果我开始一个交互式 bash 会话,这个命令在路径上,但如果我只是运行命令,则不是。

在这种情况下,使用可执行文件的完整路径不是解决方法,因为该命令依赖于其他环境变量,就像PATH在 bash 交互式会话中设置的一样,但如果我直接运行该命令则不会。

BMi*_*tch 8

在你的第一个例子中:

docker exec -i -t my_container bash -c "echo $PATH"
Run Code Online (Sandbox Code Playgroud)

这将$PATH使用您的 docker 客户端上的 shell 在容器外评估变量,然后将扩展值作为命令传递到容器内运行。您可以将上面的值与在echo $PATHdocker 之外的命令行上运行进行比较,并查看它们是相同的。

在你的第二个例子中:

docker exec -i -t my_container bash 
root@21e6d898c3c2:/# echo $PATH
Run Code Online (Sandbox Code Playgroud)

这将评估$PATH容器内的变量。

您可以转义第一个示例,或单引号以防止工作站上的 bash shell 扩展它,以便在容器内对其进行评估。以下任一方法都可以:

docker exec -i -t my_container bash -c "echo \$PATH"
docker exec -i -t my_container bash -c 'echo $PATH'
Run Code Online (Sandbox Code Playgroud)


Max*_*vak 7

尝试-l的选项bash。它将在登录 shell 中运行并加载/etc/profile.

docker exec -i -t my_container bash -lc "echo $PATH"
Run Code Online (Sandbox Code Playgroud)


chi*_*cks 6

-c指定时bash不作为交互式登录shell运行,因此它不会读取相同的启动脚本。/etc/profile, ~/.bash_profile, ~/.bash_login, or 中设置的任何内容~/.profile肯定会被跳过。

此外,如bash手册页所述:

Bash 尝试确定它何时在其标准输入连接到网络连接的情况下运行,如由远程 shell 守护程序(通常rshd)或安全 shell 守护程序执行时sshd。如果 bash 确定它正在以这种方式运行,它会从~/.bashrc 和 读取和执行命令 ~/.bashrc,如果这些文件存在并且是可读的。

因此,如果它不认为您正在通过网络进行连接,则它可能不会读取该.bashrc文件,这将跳过上一步未跳过的所有内容。

解决方案

要解决此问题,我将创建一个脚本,将 设置PATH为合适的内容,然后运行该命令。如果您想使用现有.profile文件或其他文件,则可以在脚本中使用

  • 为什么不使用 bash -l -c "command" 运行 (6认同)