我在/ etc/sudoers中有这个:
%wheel myhostname =NOPASSWD: /bin/bash -c "echo foo && echo bar", \
/bin/bash -c echo foo
Run Code Online (Sandbox Code Playgroud)
在sudo /bin/bash -c echo foo没有提示输入密码的情况下执行工作.
但是,sudo /bin/bash -c "echo foo && echo bar"仍然要求输入密码.
我尝试了很多变化,但没有被接受.
哪里出错?/如何允许-c后跟多个命令?
问题在于您的外壳如何解释参数。如果我在bash中(大多数其他shell都以相同的方式工作),然后键入命令
sudo /bin/bash -c "echo foo && echo bar"
Run Code Online (Sandbox Code Playgroud)
sudo随其后的所有内容作为参数被调用。但是,shell在将每个参数传递给之前先对其进行处理sudo。它的作用之一是删除引号中的引号。因此,sudo作为其argv值获取的参数是一个看起来像这样的数组(每行一个参数):
/bin/bash
-c
echo foo && echo bar
Run Code Online (Sandbox Code Playgroud)
sudo将它们与空格结合起来,然后将其与sudoers文件中的命令进行比较(实际上,此操作要复杂得多,因为它会进行通配符替换等)。因此,为了检查权限,它实际上看到您正在执行的命令是
/bin/bash -c echo foo && echo bar
Run Code Online (Sandbox Code Playgroud)
当我将该命令放在sudoers文件中时,输入以下命令时不会提示我输入密码
sudo /bin/bash -c "echo foo && echo bar"
Run Code Online (Sandbox Code Playgroud)
但是,当我输入任何这些命令或其他类似命令时,也不会提示我输入密码。
sudo /bin/bash "-c echo foo && echo bar"
sudo /bin/bash "-c echo" foo "&& echo" bar
sudo /bin/bash -c echo "foo && echo" bar
Run Code Online (Sandbox Code Playgroud)
一般而言,据我所知,没有办法sudo(或任何程序)确切地知道输入了什么命令,只有通过外壳程序将其转换为执行目的的命令。
至少在我的sudo(OS X 10.9,sudo 1.7.10p7)中,引号中的引号/etc/sudoers是字面匹配的。也就是说,指定
/bin/bash -c "echo foo && echo bar"
Run Code Online (Sandbox Code Playgroud)
意味着用户实际上必须运行
sudo /bin/bash -c '"echo foo && echo bar"'
Run Code Online (Sandbox Code Playgroud)
即引号必须传递给程序。
因此,您所要做的就是在 /etc/sudoers 中删除引号:
%wheel myhostname =NOPASSWD: /bin/bash -c echo foo && echo bar
Run Code Online (Sandbox Code Playgroud)
虽然这看起来有点奇怪,但它在我的机器上完全有效:用户可以在/bin/bash -c "echo foo && echo bar"没有密码的情况下执行。这是有效的,因为根据man sudoers,唯一必须转义的字符是',', ':', '=' and '\'。
请注意,这意味着sudo基本上将所有命令行参数仅与空格连接在一起以确定匹配:用户也可以执行/bin/bash -c "echo foo" "&&" "echo bar". 因此,您必须注意,任何参数都不会单独构成安全风险(例如foo, 、&&和bar不是可用于攻击您的计算机的东西)。