Bash - 使用标准输入和 EOF 的 Sudo 身份验证

Bash - Sudo authentication using stdin and EOF

我在使用 sudo -Sbash -cEOF 进行身份验证时遇到问题。

在下面的代码中:

--

#!/bin/bash

pass="my_pass\n"
#echo -e $pass

ssh -T my_user@my_server << EOF
    whoami
    pwd
    echo $HOSTNAME
    (sleep 3; echo -e $pass; sleep 3) | sudo -S -u batchuser whoami
    (sleep 3; echo -e $pass; sleep 3) | sudo -S -H -u batchuser bash -c "pwd"
    (sleep 3; echo -e $pass; sleep 3) | sudo -S -u batchuser bash -c "echo $HOSTNAME"
    (sleep 3; echo -e $pass; sleep 3) | sudo -S -u batchuser bash -c "touch test"
    (sleep 3; echo -e $pass; sleep 3) | sudo -S -u batchuser bash -c << TEST1
        sleep 10; echo -e $pass; sleep 3
        whoami
        pwd
    TEST1
EOF

输出:

my_user@my_pc> ./test_ssh.sh
my_user@my_server's password:              <-- I wrote the password here
my_user
/home/my_user
my_pc                                      <-- It's not 'my_server'
Mot de passe de my_user: batchuser
Mot de passe de my_user: /home/my_user     <-- It's not '/home/batchuser'
Mot de passe de my_user: my_pc             <-- It's not 'my_server'
Mot de passe de I86671: touch: cannot touch `test': Permission denied
Mot de passe de my_user: Sorry, try again.
Mot de passe de my_user: Sorry, try again.
Mot de passe de my_user: Sorry, try again.
sudo: 3 incorrect password attempts
my_user@my_pc>

你知道我怎么用EOF传递密码吗?
为什么 bash -c 的输出不是预期的?

第一个问题是在HereDocument中环境变量默认在调用shell中展开。您可以通过使用 "EOF" 和引号作为起始分隔符或转义 $HOSTNAME 等变量来防止此行为。 你应该认真阅读 man bash 关于 Here Documents 的内容。就像三个短段落。

第二个 sudo 的问题在于,虽然使用了 -H,但它只设置了 $HOME 环境变量,而没有更改目录。 "cd; pwd" 应该可以解决这个问题。

来自man sudo

-H, --set-home

Request that the security policy set the HOME environment variable to the home directory specified by the target user's password database entry. Depending on the policy, this may be the default behavior.

第三个 sudo 可能会带来更大的问题,因为该变量嵌套得更深。对于 $HOSTNAME 它当然是一样的,但对于其他环境变量,您可能必须在前面堆放一堆反斜杠以保护它们。想想\$UID.

至于 touch test,您必须将目录更改为您有权写入该文件或以某种方式处理权限的地方。

最后一个 sudo 的问题是管道和 HereDoc 都被设置为 sudo 命令的 stdin,而不是 bash,所以不知何故这两个混淆了向上。 你想要的是:

(sleep 3; echo -e $pass; sleep 3) | sudo -S -u batchuser bash -c "
    whoami
    pwd
"

最后一件小事是(恕我直言)像这样编写代码可能会更好读,因为 sleep 也是不必要的:

<<<$pass  sudo -S -p "" bash -c "cd; pwd"