如何在 ash 中保留环境变量,Almquist shell?

DJV*_*DJV 7 path environment-variables profile ash docker

如何让 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 之外是否可行。

我已经阅读了thisthis以试图理解。

作为旁注,谁能解​​释这种在高山的奇怪行为?

$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

/ #
Run Code Online (Sandbox Code Playgroud)

当我们可以显示 /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"]
Run Code Online (Sandbox Code Playgroud)

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

我感谢任何信息或背景,无论是切切的。

Ste*_*ris 3

当您运行 Docker 容器时,您的运行与调用环境隔离。变量不是直接继承的。

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

例如一个go程序:

package main
import "os"
import "fmt"

func main() {
    for _, e := range os.Environ() {
        fmt.Println(e)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

FROM scratch
ADD tester /
ENTRYPOINT ["/tester"]
Run Code Online (Sandbox Code Playgroud)

如果我们运行这个:

$ docker run tst
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=e598bf727a26
HOME=/root
Run Code Online (Sandbox Code Playgroud)

这些是 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=/
Run Code Online (Sandbox Code Playgroud)

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

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

$ docker run -e myvariable=testing -it alpine /bin/sh
/ # echo $myvariable
testing
Run Code Online (Sandbox Code Playgroud)

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

$ cat Dockerfile 
FROM alpine
ENV myothervar=anothertest

$ docker build -t myalpine .
...

$ docker run -it myalpine
/ # echo $myothervar
anothertest
Run Code Online (Sandbox Code Playgroud)

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