解决方案

解决方案

以下内容如何$PATH直接来自bash -c

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

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

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

为了给这个问题提供一些背景信息,我想在容器中运行一个命令docker exec,如果我启动一个交互式 bash 会话,这个命令就在路径上,但如果我只是运行该命令,它就不在路径上。

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

答案1

-c指定bash不运行时交互的登录shell,这样它就不会读取相同的启动脚本。在/etc/profile~/.bash_profile~/.bash_login或中设置的任何内容~/.profile都肯定会被跳过。

另外,正如bash手册页所解释的:

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

因此,如果它认为您没有通过网络连接,它可能也不会读取该.bashrc文件,从而跳过上一步未跳过的所有内容。

解决方案

为了解决这个问题,我会创建一个脚本,将设置PATH为合适的值,然后运行命令。如果您想使用现有文件.profile或其他文件,那么您可以只需获取它在你的脚本中。

答案2

在您的第一个例子中:

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

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

在你的第二个例子中:

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

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

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

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

答案3

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

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

相关内容