Lau*_*ura 1 command-line bash sudo redirect
我正在尝试使用sudowith-S通过命令行发出密码。
$ sudo -S <<< "mypassword" command
Run Code Online (Sandbox Code Playgroud)
这有效,但它不允许交互式命令。像nano例如:
$ sudo -S <<< "mypassword" nano /tmp/foo
Run Code Online (Sandbox Code Playgroud)
它会自动关闭 nano 会话。同apt-get:
$ sudo -S <<< "mypassword" apt-get install foo
Run Code Online (Sandbox Code Playgroud)
它在我可以按“y”安装 foo 之前关闭。我知道我可以通过-yapt 但总的来说,这令人沮丧。
也尝试过这样的东西,但它仍然无法参与交互式会话:
$ sudo -S <<< "mypassword" -H -u root bash -c "apt-get install foo"
Run Code Online (Sandbox Code Playgroud)
是否可以在-S不取消所有交互式 shell 的情况下与 sudo一起使用?
您使用的是<<<aka here-string,这种类型的重定向是通过立即取消链接(又名删除)的临时文件实现的。还知道进程从父级到子级继承文件描述符(以及其中的标准输入)1,当sudo -S执行时,它从原始 shell 传递给它的临时文件(读取sudo -S命令的那个)读取它的输入。你可以看到它在行动:
$ sudo -S bash -c 'ls -l /proc/self/fd/0' <<< "mypasswd"
lr-x------ 1 root root 64 Feb 26 13:12 /proc/self/fd/0 -> '/tmp/sh-thd.cUOOXU (deleted)'
Run Code Online (Sandbox Code Playgroud)
因此,在这种情况下会nano报告Too many errors from stdin错误。可以做的是手动重新连接stdin来自哪里。
$ sudo -S bash -c 'exec < /dev/tty; nano /tmp/foobar' <<< "mypasswd"
$ sudo -S bash -c 'nano /tmp/foobar < /dev/tty' <<< "mypasswd"
Run Code Online (Sandbox Code Playgroud)
这两个命令中的任何一个都将nano正确启动,其他命令也将正常启动。/dev/tty是代表当前终端设备的特殊文件,它实际上与stdin“普通”交互式 shell 相同(当然我过于简化了该语句)。
该主题的另一个变体是$ sudo -S bash -c 'nano /tmp/foobar 0>&1' <<<"mypasswd"。stdout有效地指向同一个终端设备(除非您明确提供了重定向以将 stdout 指向其他地方)。因此,如果我们stdin指出是 的duplicate stdout,它实际上是与上述相同的解决方案。(如果你想知道我为什么突出显示dup部分,那是因为dup2()syscall 是负责处理所有文件描述符的人)
但是,请注意,我不鼓励sudo -S在交互式 shell 中使用,因为密码将保留在 shell 的历史记录中
$ sudo -S bash -c 'sleep 3m' <<< "ohnomypassword"
^C
$ history 2
2016 sudo -S bash -c 'sleep 3m' <<< "ohnomypassword"
2017 history 2
Run Code Online (Sandbox Code Playgroud)
sudo -S更适合与其他进程一起使用,sudo -S希望通过管道输入,理想情况下来自zenity --password或dialog --passwordbox "foobar text" 200 200(请参阅关于对话框的extra1和extra2)。
1. 如果文件在O_CLOEXEC标志设置的情况下打开,则通过execve()标志类型产生的子进程或替换进程将无法访问该文件描述符 - 即它将被关闭execve()