切换用户而不创建中间过程

Mat*_*ner 15 linux bash shell sudo exec

我可以使用sudosu以另一个用户身份执行命令.通过组合exec,我能够用sudo或替换当前进程su,以及运行命令的子进程.但我想用另一个用户运行的命令替换当前进程.我怎么做?

使用sleep inf命令和someguy用户进行测试:

exec su someguy -c 'sleep inf'
Run Code Online (Sandbox Code Playgroud)

这给了我pstree:

bash???su???sleep
Run Code Online (Sandbox Code Playgroud)

exec sudo -u someguy sleep inf
Run Code Online (Sandbox Code Playgroud)

bash???sudo???sleep
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,我只想要sleep命令,bash作为父命令.

我希望我能有什么的一些序列做到这一点由C setuid()exec().

Nah*_*eul 7

sudo sleep和之间的区别在于exec sudo sleep,在第二个命令中,sudo进程替换了bash映像,并在sleep退出时调用shell进程退出

pstree -p $$
bash(8765)???pstree(8943)

((sleep 1; pstree -p $$ )&); sudo -u user sleep 2
bash(8765)???sudo(8897)???sleep(8899)

((sleep 1; pstree -p $$ )&); exec sudo -u user sleep 2
sudo(8765)???sleep(8993)
Run Code Online (Sandbox Code Playgroud)

然而,新的过程sudosu分叉的事实取决于设计及其实现(这里找到一些来源).

来自sudo手册页:

流程模型

当sudo运行命令时,它调用fork(2),如上所述设置执行环境,并在子进程中调用execve系统调用.主sudo进程等待命令完成,然后将命令的退出状态传递给安全策略的close函数并退出.如果配置了I/O日志插件,或者安全策略明确请求它,则会创建一个新的伪终端("pty"),并使用第二个sudo进程在用户现有的pty和用户之间中继作业控制信号.正在运行命令的新pty.这个额外的过程使得例如暂停和恢复命令成为可能.没有它,命令将在POSIX中称为"孤立的进程组",并且它不会接收任何作业控制信号.作为特殊情况,如果策略插件没有定义close函数并且不需要pty,则sudo将直接执行命令而不是首先调用fork(2).sudoers策略插件仅在启用I/O日志记录,需要pty或启用pam_session或pam_setcred选项时定义close函数.请注意,pam_session和pam_setcred在使用PAM的系统上默认启用.


Ljm*_*art 5

我不同意观察和结论.见下文:

我创建了两个shellcripts:

$ cat just_sudo.sh
#!/bin/bash
sudo sleep inf
$ cat exec_sudo.sh
#!/bin/bash
exec sudo sleep inf
Run Code Online (Sandbox Code Playgroud)

所以,一个有一个exec,一个没有.如果我pstree去看看起始情况,我得到:

$ pstree $$
bash???pstree
$ echo $$
17250
Run Code Online (Sandbox Code Playgroud)

这给了我基线.接下来我启动了两个脚本:

$ bash just_sudo.sh &
[1] 1218
$ bash exec_sudo.sh &
[2] 1220
Run Code Online (Sandbox Code Playgroud)

然后,pstree给出:

$ pstree $$
bash???bash???sleep
     ??pstree
     ??sleep
Run Code Online (Sandbox Code Playgroud)

第一个是just_sudo,第二个是exec_sudo.两者都以root身份运行:

$ ps -ef | grep sleep
root      1219  1218  0 14:01 pts/4    00:00:00 sleep inf
root      1220 17250  0 14:01 pts/4    00:00:00 sleep inf
Run Code Online (Sandbox Code Playgroud)

再一次是第一次是just_sudo第二次exec_sudo.您可以看到,睡眠的父PID exec_sudo是从中启动脚本的交互式shell,PID是1220,这是我们在后台启动脚本时看到的PID.

如果您使用两个终端窗口并且不将它放在后台,这也可以:

terminal 1                            terminal 2
$ echo $$
16053                                 $ pstree 16053
                                      bash
$ sudo sleep inf
                                      $ pstree 16053
                                      bash???sleep
^C
$ exec sudo sleep inf
                                      $ pstree 16053
                                      sleep
^C
 ( window is closed )
Run Code Online (Sandbox Code Playgroud)

因此,在我的 linux系统上,行为并不像你建议的那样.subdo可能保留在进程树中的唯一方法是它是否在现有的tty中运行(所以没有exec),或者如果它被调用了伪终端,例如exec sudoedit.

  • 你的回答有点不能接受我的支持.您的观察和结论与问题作者的观察和结论不同的原因是因为您在后台运行`*_sudo.sh`脚本(在命令行末尾使用`&`字符).可以在源代码中找到它的解释 - 请参阅https://www.sudo.ws/repos/sudo/file/tip/src/exec.c并注意标有注释的代码片段*直接执行*).使用提供的信息改善您的答案,您将收到我的upvote. (2认同)