【问题标题】:Why can I run a Bash function with the 000 permissions?为什么我可以使用 000 权限运行 Bash 函数?
【发布时间】:2010-10-15 14:26:17
【问题描述】:

我可以运行具有 000 权限的 Bash 函数并不完全正确,但差不多。我的代码是:

#!/bin/bash
function hello {
echo Hello! }

hello-file 有权限:

-r--------  1 UnixBasics hello_file

首先,我使用当前权限输入:

$ . ./hello_file;hello

调整是在运行 bash 脚本之前将 400 权限更改为 000:

$ chmod 000 hello_file
$ . ./hello_file;hello                                             [1]
-bash: ./hello_file: Permission denied 
Hello!

它给出一个错误,但它不会停止运行该函数。我不明白。我现在取消设置你好功能:“取消设置你好”。我收到错误:

-bash: ./hello_file: Permission denied
-bash: hello: command not found

为什么我第一次没有得到它们?它与缓存、缓冲区或类似的东西有关吗?为什么我可以使用 000 权限 [1] 运行 Bash 脚本?

【问题讨论】:

  • 第一行应该是“#!/bin/bash”。
  • 非常感谢 Andrew Medico,他对我的文章进行了批判性解读。因此,我在写作中发现了一些令人讨厌的错误,其中似乎存在一些小争论。希望现在一切都是正确的。
  • 或者你可以 "mkdir /bash ; cp /bin/bash /bash/bin" :-) 不,不要真的这样做,我只是在开玩笑。

标签: bash file-permissions


【解决方案1】:

没有运行脚本,你采购(包括)它。要获取脚本,您只需要读取权限。

顺便说一句,函数只是存在,它们没有权限。获取文件并定义函数后,您可以根据需要运行它。


更新:

为什么我第一次没有得到它们?它与缓存、缓冲区或类似的东西有关吗?

是的,就像 Pax 回答的那样,你好可能是之前从文件的先前来源中定义的。您可能会对 sourcing(“.”内置命令)的作用感到困惑。 Sourcing 读取文件并在当前 shell 中运行它的所有命令,然后返回到提示符。因此,如果您运行该文件一次,其函数将在当前 shell 实例中定义,并且它们会一直保留在那里,直到您完成该 shell 会话(或取消设置它们)。

为什么我可以使用 000 权限 [1] 运行 Bash 脚本?

你不能。请注意,它会显示错误。引用你的输出:

$ . ./hello_file;hello                                             [1]
-bash: ./hello_file: Permission denied 
Hello!

您在一个命令行中执行了两个命令。采购失败并显示“权限被拒绝”。 “你好!”输出来自文件的先前来源。当您取消设置并再次尝试相同的命令行时,您只是自己证明了这一点。

你不能称之为缓存......这就是shell的工作方式。您获取另一个文件,它的所有定义都包含在当前的 shell 会话中并留在那里。如果您确实运行脚本(不是采购),那么您不应该在当前会话中得到任何残留物。

$ chmod +x hello_file
$ ./hello_file           # note: executed, not sourced
$ hello
-bash: hello: command not found

【讨论】:

  • 这不对。使用 perm=100,它仍然不允许您获取脚本,给出“权限被拒绝”。 Sourcing 只是在当前 shell 的上下文中执行,而不是在子 shell 中执行。建议你自己试试。
  • Pax:我不是在争论 100 或 000 权限,我只是在争论 exec 权限不会影响采购(“.”内置命令),这就是他真正在做的事情.为什么投反对票?
  • 投反对票是因为你错了 - 试试看。如果 perm = 000 或 100,则采购不起作用。
  • 如果你证明我错了,我会删除-1,没问题。但我已经测试过了。
  • 再一次,我从未提到可以使用 000 或 100 进行采购。请再次阅读我的答案并告诉我我提到 000 或 100 的位置。
【解决方案2】:

最可能的解释是您在 hello_file 受到保护之前运行了它并且该函数已经创建。然后您保护了您的脚本(您在命令中说 100,但在文本中提及 000)。

所以,脚本不会运行。但是 hello() 仍然是从你之前的运行中定义的。

尝试打开一个新的shell或者直接执行unset hello

【讨论】:

  • 您的答案听起来像是在猜测。我认为给出的第一个答案是正确的——他只是在一个可读文件中采购。 Shell 函数没有也不尊重权限。
  • 这不是猜测,我测试过。并且权限在创建函数的文件上,而不是函数本身。
【解决方案3】:

在将模式更改为 100 之前,您是否获取了脚本(即运行“../hello_file”)?如果是这种情况,那么“hello”函数仍然只是加载到 bash 中。随后尝试获取不可读文件不会改变这一点。要正确测试,请确保启动 fresh shell。

【讨论】:

  • 我做了一些更正,并为问题添加了更多细节。显然,它们对于回答问题至关重要。
【解决方案4】:

为了运行程序(无论是 bash 脚本还是二进制可执行文件),您需要具有执行权限。输入命令时,第一个字(如下面的./foo)指定要运行的命令,即作为单独的进程启动;对于 shell 脚本,它执行#! 行中列出的 shell 解释器的新副本,并使用该解释器运行程序。

$ ls -l foo -rw-r--r-- 1 lambda lambda 23 Mar 25 20:02 foo $ chmod 744 foo # 或 chmod u+x foo $ ls -l foo -rwxr--r-- 1 lambda lambda 23 Mar 25 20:02 foo $ ./foo 你好

当您使用. 命令时,这是一个shell 内置命令,表示将文件源到当前shell;这意味着它执行文件中的命令,就好像您从命令行运行它们一样,就在当前文件中。您只需要读取权限即可获取文件。例如,如果您在子进程中设置了一个变量,它不会改变当前 shell 中的值;但是如果你将一个 bash 脚本输入到当前的 shell 中,那么它确实会改变值:

$ foo=bar $ cat 设置变量 #!/bin/sh 富=你好 $ ./setvariables $ 回声 $foo 酒吧 $ . ./set变量 $ 回声 $foo 你好

shell 函数(如您的示例中)很像一个变量,但它的作用类似于当前 shell 中的命令。因此,当您使用 . 获取 hello_file 时,它会在当前 shell 中定义该函数,并且它可以像您定义的任何其他 shell 函数一样执行。

就权限而言,我敢打赌,在将权限更改为 100 之前(这意味着只能执行,不可读,这对于文件来说是相当无用的,因为您需要能够读取并执行它做任何事情),您已经将文件获取到您当前的 shell 中。这意味着该函数已经定义,并且定义后文件的权限无关紧要;一旦在当前shell中定义了函数,你甚至可以删除文件,只要那个shell仍然打开,函数仍然会被定义。

编辑:正如我从您编辑的问题中看到的那样,一旦您取消设置该功能,就会出现错误。这向我强烈表明我的假设是正确的,并且您在更改权限之前已经获取了该文件。正如我所解释的,获取和执行文件是完全不同的操作,一旦你获取了一个文件,它的权限(或存在)就无关紧要了。该函数已加载到当前运行的 shell 中。您可以通过在执行unset hello 后运行您的原始实验来判断;如果你chmod 000它,你不应该有读取权限,那么函数就不会被定义。

【讨论】:

  • 呃,为什么投反对票?我的描述中是否有任何错误或无用之处?
  • 这大部分是正确的,但与问题无关(为什么可以 - 显然 - 获取模式 100 文件)。特别是,文件不需要是可执行的,只能是可读的。
  • 我添加了一段关于权限的说明;他在获取文件时显然遇到了权限错误,因此他必须从先前的调用中获得定义。我之所以描述采购和运行之间的区别,是因为我认为这就是混乱所在。
  • 你确定第一行吗?我能够得到输出“你好!”即使我在命令之前取消设置 hello 功能,权限也为 400。我没有“运行”程序的执行权限。还是我只是对“运行”这个词的理解有误?
  • 我认为您对“跑步”一词的理解是错误的。这就是我试图解释的。运行程序(如我的第一个示例所示)与采购程序(如第二个示例所示)不同。你明白我解释的那部分吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2021-09-08
  • 2011-07-15
  • 1970-01-01
  • 2023-04-09
  • 2011-05-08
  • 1970-01-01
相关资源
最近更新 更多