为什么非root用户不能使用通配符表达式?

为什么非root用户不能使用通配符表达式?

我正在使用通配符表达式来匹配文件名。

对于普通的非 root 用户来说,会发生以下情况:

debian@MiWiFi-R3-srv:~$ sudo ls  /var/log/apache2/*[0-9].gz
ls: cannot access '/var/log/apache2/*[0-9].gz': No such file or directory

sudo su在我切换到 root 用户并尝试相同的命令后,发生了以下情况:

root@MiWiFi-R3-srv:/home/debian# ls  /var/log/apache2/*[0-9].gz
/var/log/apache2/access.log.10.gz  /var/log/apache2/error.log.10.gz
/var/log/apache2/access.log.11.gz  /var/log/apache2/error.log.11.gz
/var/log/apache2/access.log.12.gz  /var/log/apache2/error.log.12.gz

为什么这个通配符表达式可以被用作root,但不能被普通的非root用户使用?

答案1

/var/log/apache2/*[0-9].gz子字符串中*[0-9]路径名扩展shell 机制。既不是sudo也不是ls。这在之前就发生了sudo,甚至ls在开始之前就发生了。

要扩展/var/log/apache2/*[0-9].gzshell,需要检查 的内容/var/log/apache2/。在我的 Debian 10 中,权限是rwxr-x---,所有权是root:adm。实际上,root 的 shell 可以检查内容,但普通用户的 shell 不能。

因此,模式对于 root 来说会展开,但对于普通用户来说,它保持原样。模式既不展开,sudo也不ls展开,最终普通用户(提升权限)ls会尝试列出/var/log/apache2/*[0-9].gz确切的信息;没有这样的文件或目录。

这应该适用于普通用户:

sudo sh -c 'ls /var/log/apache2/*[0-9].gz'

在这种情况下sudo将运行升高 sh而这个壳就会成功扩大格局。

(一开始我想sudo -s …这么做,但是

答案2

与 Windows/DOS 不同,在 Unix 系统中,shell 在运行命令之前会扩展 glob。在这种情况下,shell 使用您的 UID 而不是 root 运行,因此它无法读取该目录。

不匹配情况下的默认行为是逐字传递 glob 表达式。 例如如果你ls xyz*xyz在普通 shell 中运行,你会看到ls: cannot access 'xyz*xyz': No such file or directoryfrom ls,因为它将该字符串作为参数。

就像您运行以将文字字符串ls '*'传递给一样。(删除引号也是 shell 的工作,因此命令无法判断其参数是否被引用。)*ls

您可以在 bash 中更改此行为,例如,这shopt -s failglob意味着相同的ls xyz*xyz命令将给出 bash: no match: xyz*xyz 没有ls根本无法调用。(如果您使用过sudo,您会注意到在收到此错误消息之前它并没有提示您输入密码。)

failglob当尝试读取您没有读取权限的目录时,会产生相同的“不匹配”错误,不幸的是,当 bash 对open目录进行系统调用时,不会警告您 EPERM 错误。bash: no match: /var/log/private/*

(还有shopt -s nullglob,其中不匹配的 glob 表达式被删除而不是逐字传递。那么您的sudo ls /...*命令就会令人困惑地仅作为运行sudo ls。这可能对于您可能想要执行*.gz *.tgz *.tar或其他操作的脚本很有用,并且不会因扩展失败而出现错误。可能不是您通常想要用于交互式使用的东西。)


您可以使用shopt -u failglob或任何方式联合国在 shell 中设置这些选项,如果设置了就尝试一下。

相关内容