2

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

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

hello 文件具有以下权限:

-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 脚本?

4

4 回答 4

11

不是在运行脚本,而是在采购(包括)它。为了获取脚本,您只需要读取权限。

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


更新:

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

是的,就像 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
于 2009-03-25T23:59:06.420 回答
5

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

因此,脚本将不会运行。但是 hello() 仍然是从您之前的运行中定义的。

尝试打开一个新的 shell 或只执行unset hello.

于 2009-03-26T00:02:19.720 回答
2

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

于 2009-03-26T00:04:28.730 回答
2

为了运行程序(无论是 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_fileusing时.,它会在当前 shell 中定义该函数,并且它可以像您定义的任何其他 shell 函数一样执行。

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

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

于 2009-03-26T00:12:43.453 回答