为什么当我从网上下载二进制文件时,它没有设置可执行权限,但当我使用 gcc 构建二进制文件时,它却设置了可执行权限?

为什么当我从网上下载二进制文件时,它没有设置可执行权限,但当我使用 gcc 构建二进制文件时,它却设置了可执行权限?

例如,如果我有文件 hello.c,其中仅包含:

int main() {
   printf("Hello world");
   return 0;
}

我用 gcc 构建了它,gcc hello.c -o hello然后我就可以运行./hello它了。

但是,如果我尝试使用 eg 从网络下载二进制文件curl,我首先必须使用 chmod 设置权限,然后才能运行它。有理由吗? gcc 和/或curl 是否对文件设置了一些默认权限?

答案1

如何curl知道该文件是可执行的?从技术上来说,它可以检查其内容,但这远远超出了curl预期的范围。

默认权限由umask(http://en.wikipedia.org/wiki/Umaskumask)并且在从程序派生的权限之上可以添加可执行位(或完全使用不同的权限)。例如,gcc知道它正在生成可执行文件,因此设置 exec 位。另一方面,curl并​​不意味着创建可执行文件,因此仅使用默认权限。

答案2

当您通过 HTTP 下载文件时,您只会收到文件的内容,而不会收到其元数据,例如创建日期、权限等。

使用包含此元信息的不同协议,或者,如果您有权访问服务器,请在包含元数据信息的容器(例如 tar 文件)中提供文件。

如果这是一个严重的反复出现的挫败感,您还可以编写一个包装器,curl尝试猜测正确的权限并在下载完成时设置它们(提示:file猜测文件类型)。

答案3

在unix系统中,一个文件是否可执行仅取决于它的权限,而不是它的名称或内容。 (如果文件格式不是有效的可执行文件,系统将尝试执行并将其视为执行程序时可能出现的错误之一,以及资源不足、缺少库等)

您从网络下载的大多数文件并不意味着可执行,因此curl 不会尝试使文件可执行。即使该文件本来要执行,您现在可能不想执行它;例如,您可能想要对其进行审查,并且仅在通过审查后才使该文件可执行。

另一方面,gcc 或任何其他编译器旨在生成可执行程序,因此它会采取必要的步骤也就不足为奇了。对于 gcc,这是编译过程的最后阶段之一。你可以观察它斯特雷斯:

$ strace -f gcc a.c
23429 execve("/usr/bin/ld", ["/usr/bin/ld", "--eh-frame-hdr", "-m", "elf_i386", "--hash-style=both", "-dynamic-linker", "/lib/ld-linux.so.2", "-z", "relro", "/usr/lib/gcc/i486-linux-gnu/4.3."..., "/usr/lib/gcc/i486-linux-gnu/4.3."..., "/usr/lib/gcc/i486-linux-gnu/4.3."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/lib/../lib", ...], [/* 82 vars */]) = 0
23429 chmod("a.out", 0755)              = 0
23429 exit_group(0)                     = ?

换句话说,链接器,这是编译的最后一个阶段并生成可执行文件,作为最后一步将输出文件的权限更改为可执行。

答案4

  1. “二进制”与“可执行文件”不同。将文件指定为“二进制”只是一种启发式方法,这意味着文件的内容通常不可读。将文件指定为“可执行文件”意味着它包含某种可以“运行”的程序(即使是非二进制形式,例如 shell 脚本)。无数的二进制格式只是数据容器。
  2. 您的命令生成的二进制文件gcc总是将是一个主要用作可执行文件的文件。
  3. 您不能信任来自互联网的文件。不要试图猜测一个文件是否应该可执行,无论如何这是不可能的,因为即使是散文也可以用作 shell 脚本,curl而其他程序将简单地应用umask并将任何内容留给gun.shoot(self.foot)用户。

相关内容