1

所以我想我有一点用户权利问题。一直在编写 Web 服务器控制面板的脚本。

在此脚本中,我将用户的所有文件夹都列在一个数组中,以便将其与用户输入进行比较。(每个用户都是一个新客户,每个客户可以有多个站点)。直到上周五我运行这个命令:

[rjo@WEB ~]$ sudo ls -d /home/hejhej/*/ 2>/dev/null

从我自己的用户(rjo)运行命令一切正常。但是现在当我运行命令时没有任何反应,所以我删除了“2>/dev/null”并再次尝试,现在我得到了这个:

[rjo@WEB ~]$ sudo ls -d /home/hejhej/*/
ls: cannot access /home/hejhej/*/: No such file or directory

但是当从 root 运行它时,一切正常:

[root@WEB ~]# ls -d /home/hejhej/*/
/home/hejhej/bumbum.dk/

这是来自 visudo 文件的关于我的用户的行。

rjo     ALL=(ALL)       NOPASSWD: ALL

如果您需要任何其他信息来帮助,请告诉我,我会发布。

4

1 回答 1

1

如果您的用户没有足够的权限/home/hejhej列出其内容,则会发生这种情况。

当你运行时:

sudo ls -d /home/hejhej/*/

您的外壳尝试进行文件名通配。如果它不能读取那个目录,它就不能展开任何东西。因此,文字字符串/home/hejhej/*/保持原样,并作为参数传递给通过vials运行。看来您没有在该目录中调用目录,因此失败。rootsudo*ls

你需要 shell 开始sudo在这里做 globbing。一种选择可能是:

sudo sh -c 'ls -d /home/hejhej/*/'

如果您希望搜索的文件夹包含一个 shell 变量,那么'硬引号将不起作用 - 这可以防止您的 shell 出现通配符(好),但也可以防止您的 shell 进行变量扩展(这里不好)。您应该改用双引号 ( "),以便您的 shell 完成变量扩展:

sudo sh -c "ls -d /home/$username/*/"

如果您想将该命令的输出捕获到变量中,请更喜欢$()命令替换的形式而不是反引号 ( `) - 更容易引用:

result=$(sudo sh -c "ls -d /home/$username/*/")

现在如果$username可以包含空格(比如username="hello world"),上面的内容将不起作用 - 根 shell 将看到两个“标记”(/home/helloworld/*/)。你可以用另一层引号来解决这个问题:

result=$(sudo sh -c "ls -d /home/'$username'/*/")

考虑到引号的嵌套方式,这不会阻止您的 shell 扩展$username,但将使根 shell 能够在单个模式上正确地 glob /home/hello world/*/

现在,这仍然不完美。如果该 glob 匹配多个目录,或者匹配的目录包含空格,您将很难处理问题。但在这一点上,我建议你:

  • 阅读此建议:为什么不应该解析 ls 的输出?
  • 制作一个由 root 运行的适当脚本来处理查找适当的目录 - 如果它们简短且易于阅读,那么单行就可以了。一旦事情变得过于复杂,从长远来看,编写一个合适的脚本是一种胜利。

话虽这么说,如果您希望将另一个用户家中的目录列表放入一个数组中,那么以下(我认为特定于 bash)应该这样做,没有解析问题ls,并且应该处理文件和目录中的空格:

while read -r -d $'\0' dir ; do
  array+=("$dir")
done < <(sudo find "/home/$username" -maxdepth 1 -mindepth 1 -print0)
于 2013-05-22T10:21:14.133 回答