我试图理解非交互式和非登录 shell,但很难概念化非交互式和非登录 shell 的启动过程。
我理解事情的方式是当脚本或进程启动时:创建一个内存区域,子进程通过分叉来复制父进程的重复环境——这对我来说是有意义的。
让我困惑的是,什么时候为非交互式非登录进程或脚本定义 shell 环境?当我思考交互式 shell 是如何启动时,我有点迷失了。
我理解交互式 shell 的方式是:
- 用户将登录 ID 传递给 Linux 内核
- Linux 内核在 /etc/password 文件中查找用户并识别分配的 shell
- 外壳已启动
- shell 读取登录脚本来为用户定义 shell 环境
- Linux 产生一个命令提示符来指示 shell 已准备好接受命令
非交互式和非登录 shell 的过程是否相似?这就是我设想的工作方式:
- 该进程由父进程 fork
- Linux 标识进程将运行的用户 ID
- Linux 在 /etc/password 文件中查找用户 ID
- 外壳已启动
- 读取 BASH_ENV(如果已定义)
- 进程与 shell 交互以将命令传递给 API
出于某种原因,这看起来很笨拙,就像我错过了一些东西。有人可以让我知道我是否走在正确的道路上吗?
答案1
您实际上不需要考虑该passwd
文件。 shell 通常不处理密码身份验证。这可能比你想象的要简单一些。其他程序,例如init
和getty
实际上login
执行您在问题中描述的大部分登录过程。
大多数 shell 将会话视为交互式外壳如果 shell 使用该-i
选项启动,或者标准输出连接到终端设备(例如,/dev/tty01
)。
shell 将会话视为登录外壳如果参数零 ($0) 的第一个字符是破折号 ( -
)。某些 shell 还支持-l
产生相同效果的选项。
“登录 shell”通常是通过传统的方式启动的Linux登录流程:
该init
或其他程序getty
在每个终端上启动一个可用于登录的进程。
该getty
程序打印提示并username
从终端读取。然后以用户名作为参数getty
调用程序。login
该login
程序在文件中查找用户名passwd
,读取并验证用户的密码,设置用户的用户和组 ID 以及环境变量,并执行其他与登录相关的任务前启动登录 shell。
该进程通过在(也称为shell 内)中的程序名称login
前面添加破折号 ( ) 来通知 shell 它是登录 shell 。-
argv[0]
$0
有关登录和交互式会话概念的更多细节,您可能需要查阅 和您正在使用的特定 shell 的手册getty
页login
。不同的 shell(如 、sh
、ksh
等bash
)读取启动命令文件(如.profile
、.bash_rc
等)的方式略有不同。