即使未将脚本设置为可执行文件,它们也可以运行吗?

即使未将脚本设置为可执行文件,它们也可以运行吗?

我似乎可以运行脚本 (.sh),无论是否将其设置为可执行文件。那么这到底有什么关系呢?

答案1

假设您有myscript包含以下内容的文件:

#!/bin/bash
echo "Hello, World!"

如果你让这个文件可执行,并用 运行它./myscript,那么内核将看到前两个字节是#!,这意味着它是一个脚本文件。然后内核将使用该行的其余部分作为解释器,并将该文件作为其第一个参数传递。因此,它运行:

/bin/bash myscript

bash 读取该文件并执行其中包含的命令。

因此,对于 bash(或脚本所需的任何解释器)来说,要“执行”脚本,它只需要能够读取该文件。

因此,对于脚本来说,执行位只是让执行它更加方便一些。只要 bash 是可执行的,您始终可以使用脚本文件作为参数来运行 bash,或者以交互方式运行 bash 并将脚本逐行复制粘贴到您的终端中以执行命令。

答案2

确保您没有将“执行 shell 脚本”与“使用 sh 运行 shell 脚本”混淆。

这不会受到以下文件权限的影响file.sh

sh file.sh

您正在执行sh(解析为程序/bin/sh),它读取file.sh并执行其代码。

如果您确实执行脚本本身

./file.sh

请注意,非 Linux 文件系统(如 FAT)不支持文件权限。因此,即使您运行chmod -x file.sh,文件仍将具有其以前的权限。

执行权限由文件系统强制执行。但程序也可以通过读取文件内容来“执行”代码,从而绕过文件系统对“执行”的权限。

答案3

如果文件不可执行,execLinux 内核的系统调用将失败EACCES

虽然您可以这样做sh myprog.sh(仅读取文件并进行解释),但尝试以./myprog.sh无法工作的方式运行该程序,因为当您这样做时:

可以通过以下方法验证main.c

#define _XOPEN_SOURCE 700
#include <errno.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    char *argv[] = {"myprog", NULL};
    char *envp[] = {NULL};
    int ret;
    ret = execve("myprog.sh", argv, envp);
    perror("execve");
    printf("%d\n", errno);
    printf("%d\n", EACCES);
}

myprog.sh

#!/bin/sh
echo worked

如果myprog.sh不可执行,main则失败:

execve: Permission denied
13
13

在 Ubuntu 17.10 中测试gcc -std=c99

POSIX 7 提到:

除 fexecve() 之外的 exec 函数在下列情况下将会失败:

[EACCES] 拒绝对新进程映像文件的路径前缀中列出的目录进行搜索,或者拒绝对新进程映像文件进行执行。

进一步的理由可参见:https://security.stackexchange.com/questions/66550/unix-execute-permission-can-be-easily-bypassed-is-it-superfluous-or-whats-the

答案4

不要这样想。我能执行这个文件吗?要这样想:谁可以执行这个文件?

如果计算机是你的,文件也是你的,我相信你可以执行它。你可能需要进一步了解类似以下命令修改模式chown以及文件权限。

我希望这能有所帮助。

相关内容