问题
我在脚本中用 li.sh 创建了一个文件
#!/bin/env bash
read -p 'What is your name' name
echo $name
当我尝试使用命令执行时./li.sh,我收到了权限被拒绝的错误,但是当我使用命令执行时bash li.sh,它没有任何错误。使用运行是否安全bash li.sh?
我想知道./li.sh 和 bash li.sh 之间的区别。
解决方案
我认为你无法运行 shell 脚本的原因./li.sh是你没有将文件权限设置为可执行
你可以看看这个 https://www.redhat.com/en/blog/linux-file-permissions-explained
TL;DR:你可以运行sudo chmod +x li.sh,然后继续./li.sh
假设您在运行bash li.sh和时位于同一目录中./li.sh,则它们应该以相同的方式工作。当您指定时bash li.sh,它首先运行bash并执行文件,而当您运行时./li.sh,它会读取文件,看到有#!符号,它将运行/bin/env bash,然后它将继续执行脚本。
以下是运行时发生的步骤bash li.sh:
你的 shell 会在你的 中寻找bash可执行文件$PATH,并在类似 的地方找到它/bin/bash。
你的 shell 将要求操作系统执行该程序,并将其li.sh作为参数传递
bash启动,解析其参数,并看到它被要求运行li.sh。
bash将尝试打开li.sh文件进行读取。当它这样做时,操作系统将确认您的用户对该文件具有读取权限
bash然后开始解释(“运行”)脚本的内容。
重要的是,操作系统不知道你想要这个文件做什么。一旦你用读权限打开一个文件,它就不知道你是要打印它(例如cat li.sh)、压缩它(例如zip li.sh)还是用于任何其他目的。重要的是你有读权限,你bash确实这样做了。恰好以与直接运行它相同的方式解释它。
将此与您刚运行时发生的步骤进行对比./li.sh:
你的 shell 将要求操作系统直接执行该文件
操作系统将看到它以“shebang”(#!)开头,而不是0x7F 0x45 0x4c 0x46每个Linux ELF 可执行文件都以的通常序列开头
这告诉它,它不能直接执行文件,而是需要运行 shebang 中列出的任何内容
它解析#!/bin/env bashshebang并执行/bin/env,并向其传递2个参数:bash li.sh
env然后将运行bash li.sh
bash然后将开始解释脚本。
由于操作系统知道您访问该文件的明确目的是执行它,因此您的执行权限比您的读取权限更重要。