我有一个以“root”用户身份运行的父进程。在fork()
、execl()
和 后setuid()/setgid()
,子进程将作为另一个操作系统用户(例如 user1)启动。
打印环境表明这与 root 环境相同(就像以 root 身份登录一样),而不是像以 user1 身份登录一样。为什么?
有没有办法在子进程中读取user1的环境?
答案1
每个进程都有它自己的环境,从父级复制。如果父级是一个 shell,那么就有一个概念可导出变量需要考虑这一点,但是当您直接处理等时,这并不适用exec()
。该LOGNAME
变量通常由登录 shell 设置,您只会看到未重置的剩余值。那么你是看孩子的环境。在某些系统上,您无法轻松访问父(或其他进程)环境,但在 Linux 上,您可以轻松访问(受权限限制)通过/proc
)
su
您可以通过尝试和来重现您所看到的效果su -
,后者将初始化一个 shell 登录环境,该环境将(几乎肯定)重置LOGNAME
除其他事项外,前者将保持不变。
使用env
命令是从命令行启动新进程时获得干净环境的一种方法,您应该检查execle()
系统上的文档以了解如何执行类似的操作。
答案2
您可以使用以下命令简单地检查用户环境:
su -l user_name -c "run_programm && env"
或者您可以env
使用子进程的 pid 检查子进程,
假设您的子进程 pid 是24112
,那么只需env
使用以下命令进行检查:
cat /proc/24112/environ
答案3
一些信息:
- 您可以使用
execle
或execve
向子级提供环境变量。您可以使用它来抑制父进程中不再适合子进程的环境变量,并为子进程提供其他变量。 - 您可以为孩子启动一个“登录 shell”,例如使用
bash -l
.这将像孩子一样填充环境。对于许多 shell(包括 bash),在二进制文件名称前添加连字符(即-bash
作为传递argv[0]
)具有相同的效果。这种区别的主要影响是登录 shell 将执行/etc/profile
和/或其他配置文件 shell 脚本,这些脚本又设置大量环境变量。 - 对于使用 PAM 进行身份验证和会话初始化的服务,该
pam_env
模块将负责正确初始化环境。您可以查看它及其配置,以使用它或模仿它的行为。
答案4
每个进程都有一组环境变量(可以在 shell 中通过export SOMEVAR=value
等方式设置)。它们由子进程按原样继承。如果您想重置它们,请使用extern char **environ;
来获取传递的环境(请参阅 参考资料environ(7)
),然后使用execle(3)
或execve(3)
传递带有复制的变量值的新环境数组。 David Wheeler 在他的著作中给出了关于做什么以及如何做的一些指导。《安全 Unix/Linux 编程指南》