如何在 ash(Almquist shell)中保存环境变量?

如何在 ash(Almquist shell)中保存环境变量?

如何让 ash 在启动时加载一些环境变量?

只需将它们放入 /etc/profile 中即可

/etc/profile 仅为登录 shell 读取;使用 docker(使用 alpine>busybox>ash)时频繁弹出的非登录 shell 又如何呢?

如果在环境变量 ENV 中指定,非登录 shell 将读取文件

太好了,我怎样才能确保 ENV 已设置?它本身是一个环境变量,默认为空。

本质上,我正在寻找一些保证 ash 能够读取的总体配置文件。优先选择 busybox 使用的 ash 版本(BusyBox v1.28.4,如果你想准确的话)。这样的事情存在吗?是的,我知道 docker 中的 ENV 指令,它可用于在构建 docker 映像时设置 $ENV;我仍然想知道这在 docker 之外是否可行。

我读过了努力去理解。

顺便说一句,有人能解释高山的这种奇怪行为吗?

$docker run -it alpine
/ # echo $CHARSET #proof /etc/profile has not run

/ # echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/ # env -i sh -c 'echo $PATH'
/sbin:/usr/sbin:/bin:/usr/bin
/ # echo $ENV

/ #

当我们可以显示 /etc/profile 还没有添加时,与新 shell 的默认 PATH 设置相比,PATH 中添加了哪些内容?这也不是 docker dickery,alpine 的 Dockerfile 故意最小化:

FROM scratch
ADD rootfs.tar.xz / #Automatically extracts, and I’m pretty sure that’s all
CMD ["/bin/sh"]

我之所以提到这一点,是因为看起来有人找到了一种在非登录 shell 中保留环境变量而不使用 $ENV 的方法。

我很欣赏任何信息或背景,无论多么无关紧要。

答案1

当你运行 docker 容器时,你正在运行孤立来自调用环境。变量不是直接继承的。

我们可以看到一个“干净”的环境,我们可以通过创建一个完全最小的容器来看到它。

例如一个go程序:

package main
import "os"
import "fmt"

func main() {
    for _, e := range os.Environ() {
        fmt.Println(e)
    }
}

我们可以将其构建到一个小容器中:

FROM scratch
ADD tester /
ENTRYPOINT ["/tester"]

如果我们运行这个:

$ docker run tst
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=e598bf727a26
HOME=/root

这些是由 docker 引擎创建的变量运行

因此,当您run .. /bin/sh运行一个非登录 shell 时,它只会继承 docker 创建的环境。由于它不是登录 shell,/etc/profile因此不会运行。 /bin/sh如果它们不存在,它本身会创建一些默认变量。

$ docker run -it alpine                              
/ # env
HOSTNAME=51667ed06110
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

因此,您可以通过多种方法来做到这一点。我的脑海里浮现出两个想法:

您可以使用 docker 命令行在 docker 命令行上传递环境变量-e

$ docker run -e myvariable=testing -it alpine /bin/sh
/ # echo $myvariable
testing

您可以使用以下命令基于 alpine 构建自己的镜像ENV

$ cat Dockerfile 
FROM alpine
ENV myothervar=anothertest

$ docker build -t myalpine .
...

$ docker run -it myalpine
/ # echo $myothervar
anothertest

基本上,您看到的是 docker 运行时提供一些变量,/bin/sh提供其他变量,并与调用环境隔离。

相关内容