我似乎可以运行脚本 (.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
如果文件不可执行,exec
Linux 内核的系统调用将失败EACCES
虽然您可以这样做sh myprog.sh
(仅读取文件并进行解释),但尝试以./myprog.sh
无法工作的方式运行该程序,因为当您这样做时:
- 终端上的 Bash shell 使用
exec
系统调用./myprog.sh
- Shebang 由
exec
Linux 内核的系统调用直接解释,如下所述:https://stackoverflow.com/questions/2429511/why-do-people-write-the-usr-bin-env-python-shebang-on-the-first-line-of-a-pyt/40938801#40938801 - Linux 内核拒绝执行没有可执行权限的文件
可以通过以下方法验证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] 拒绝对新进程映像文件的路径前缀中列出的目录进行搜索,或者拒绝对新进程映像文件进行执行。