alpine-linux-ash中的bashrc等价物是什么



标题几乎说明了一切(但可能还有更险恶的东西在发挥作用。(我知道当你登录时会运行/etc/profile.d/*.sh脚本,但当你只是启动一个shell时,它似乎并没有像预期的那样工作。这里有一个docker的例子:

创建一个小脚本:

$ echo "echo hello world" > startup.sh

运行alpine shell,脚本安装如下:

$ docker run -it --rm -v `pwd`/startup.sh:/etc/profile.d/statup.sh alpine sh

你只会得到一个shell提示:

/ #

它确实打印了";你好世界";当你从这里su -时:

/ # su -
hello world
2bf679a5677d:~# 

但是一个简单的sh启动一个shell是不行的:

/ # sh
/ #

那么,这里的问题是什么?这是一个晦涩难懂的Alpine Linux吗?这是一个晦涩难懂的Alpine Linux Docker镜像吗?

DockerfileRUN命令和主容器CMD不会在任何shell、任何基础Linux发行版上运行任何shell点文件。即使您的基本映像包含GNUbash,或者您手动重置SHELL以运行bash而不是标准sh,也是如此。

GNUBash参考手册可能对何时读取点文件有最好的描述。有三种情况:shell可以是非交互式shell;它可以是一个交互式shell,但不能是一个登录shell;或者它可以是一个登录shell。在Docker容器中,您遇到的shell通常不是交互式shell,如果是,它们就不是登录shell。

重要的推论是,在Dockerfiles中编写shell点文件通常是不正确的。在容器中运行命令的大多数路径都不会读取它们。如果需要设置环境变量,请改用ENV指令。

一些例子:

CMD ["/usr/local/bin/my_program"]

这个exec表单CMD根本不运行shell。没有sh进程,也不会读取任何shell点文件。

CMD my_program
# CMD ["/bin/sh", "-c", "my_program"]

这个shell表单CMD自动包装在/bin/sh -c '...'中,但生成的shell是非交互式shell,不读取点文件。

docker run --rm my_image my_program

同样,这不会运行shell。

docker run --rm my_image sh -c 'my_program'

这显式地提供了一个shell作为命令字符串的一部分,但它不是一个交互式shell。

docker run --rm -it my_image sh

主容器命令是一个shell,您没有给它一个命令,而且您提供了一个stdin;所以在这种情况下,它是一个交互式shell。如果是bash,它将读取.bashrc,但不会读取任何其他点文件。

docker run --rm -it my_image bash --login

如果你明确请求,交互式shell只是一个登录shell。几乎只有在这个调用中,整个shell点文件集才会被读取。

/etc/profile.d本身并不是一个标准的shell特性。这是一些发行版提供的便利,但bash手册中没有特别提到。比较例如

docker run --rm ubuntu cat /etc/profile
docker run --rm bash cat /etc/profile
docker run --rm alpine cat /etc/profile
docker run --rm busybox cat /etc/profile

请注意,在前三种情况下,/etc/profile文件是不同的,但它们都包含读取/etc/profile.d目录的逻辑。您的调用没有运行登录shell,因此无法读取该文件。

在正常情况下,容器运行的东西不会是shell。像docker run postgresdocker run nginx这样的预构建映像就是典型的例子:映像中封装了一些特定的软件,运行容器恰好运行该软件。启动NginxHTTP服务器不需要shell,也不读取shell点文件。

正如man ash调用部分中告诉您的那样,环境变量ENV可用于在shell启动期间指定要源代码的文件。这甚至适用于非交互、非登录的shell。

在您的Dockerfile:

ENV ENV=/home/youruser/.rc

然后您的shell将在启动期间执行CCD_ 21的内容。


这不是ash行为或Alpine行为;所有POSIX-sh实现都是如此。(bash使用BASH_ENV,但在sh兼容模式下运行时除外,此时它也会使用ENV(。

对于任何使用alpine-linux或特别是通过WSL来到这里的人,只需将.profile文件添加到根目录中。

apk update
apk add nano
cd ~
nano .profile
---
alias test='I work'
source ~/.profile
test
>>> I work

最新更新