以下内容如何$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 $PATH
docker 外部的命令行上运行的值进行比较,并发现它们是相同的。
在你的第二个例子中:
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"