0

我已经知道我可以使用该参数-l来启动一个bashksh作为一个登录 shell,所以我不必源文件之类~/.profile的,~/.bash_profile等等。但是在csh,这句话

execl("/bin/csh","csh","-l","-c","env",NULL);

是错误的,错误的信息是

Unknown option: `-l'

但我查阅了csh 手册页并发现这-l意味着

“外壳是登录外壳。仅当-l指定唯一标志时才适用。”。

所以我把句子改成

execl("/bin/csh","csh","-l",NULL);

execl("/bin/csh","csh","-c","env",NULL);

但是当我运行程序时,它在那里暂停。能告诉我怎么解决吗?</p>

4

2 回答 2

0

如果要捕获登录用户获得的实际环境,则需要登录该用户。PAM(可插入身份验证模块)可以并且确实在登录时设置环境变量,并且仅执行 shell 不会触发这些。

一种方法是创建一个伪终端,并运行/bin/login -f username(使用 root 权限,向从伪终端打开标准流)以登录指定用户。-f username应该告诉login用户是预先认证的,所以不应该出现密码对话框。写入主伪终端的所有内容都好像是用户输入的一样;从主伪终端读取获取输入(因为输入通常回显到终端)以及结果。

困难在于您必须同时读取和写入伪终端;绝对没有您可以使用的可靠顺序。(您需要将希望以用户身份运行的命令写入伪终端主机,并读取结果输出。)此外,没有简单的方法可以知道 shell 命令何时完成。它是完全异步的。

您无法使用 可靠地重建环境env,因为环境变量可以包含换行符,并且env不会以任何方式转义它们。因此,您可能应该改用辅助程序可执行文件。(环境名称-值对可以包含除 ASCII NUL 之外的所有内容\0,因此使用 NUL 分隔符输出所有环境名称-值对都可以;Linux 内核也提供/proc/self/environ了这种格式。)

如果您的父进程生成一个临时文件名,并提供一个命令来执行将 NUL 分隔的环境名称-值对写入指定文件的助手,例如"/usr/local/bin/envpairs0 /tmp/tempfile \n logout \n ",您知道任务在子进程退出时完成。然后你只需清理伪终端,读取并删除包含该用户环境的临时文件。

如您所见,这非常复杂。在具有伪终端支持的脚本语言(例如 Python)中,它稍微简单一些(例如,参见ptyPython 模块)。不知道您需要用户环境来做什么——尤其是这是一次性发生的,还是定期需要的——我很难给出更好的建议。

我可以向您展示如何实现此目的的示例程序,但由于这里对如此复杂而冗长的示例明显怀有敌意,我有点谨慎。也许您应该考虑一种更简单的方法来实现您的目标?

于 2013-09-10T11:54:41.397 回答
0

尝试以这种方式运行它:

execl("/bin/sh","sh","-l","-c","exec csh -l",NULL);

顺便说一句,你怎么知道-l其他 shell 是解决方案?;)

于 2013-09-10T05:42:34.200 回答