我有一个服务器,其中有不同种类的脚本。
这些脚本将使用不同的 shell 打开,例如:
sh ./do_one_thing.sh
bash ./do_another_thing.sh
扩展.sh
对我来说很危险,特别是如果我很长时间没有连接到服务器。或者如果有陌生人需要代替我。
我可能会意外执行sh ./do_another_thing.sh
如果我给脚本命名,会有什么不同吗do_another_thing.bash
?这将创造多一层的万无一失性。
此外,我想知道开头的 shebang 行除了提醒管理员 ( #!/bin/bash
)(如果它被覆盖)之外sh ./do_another_thing.sh
还有什么用途。在我看来,必须有一种更合适的方法来执行脚本,识别 shebang。
答案1
文件顶部的 shebang 定义了运行时运行什么解释器./name_of_file
(假设它是可执行的)。
#!/bin/cat
test 123
当您使用 运行它时,将会简单地打印上述文件./name_of_file
,因为它将运行cat name_of_file
。
#!/bin/echo
hello, world
将会简单打印name_of_file
,因为它会运行echo name_of_file
。
将其设置为 bash 或 sh 将允许您选择使用它来运行的解释器,只要您记得用 来调用它即可./name_of_file
。
话虽如此,使用.sh
sh 和.bash
bash 都可以正常工作,尽管不是标准的。文件扩展名在 Linux 上相当灵活。
答案2
在本例中,shebang 行定义了解释器/bin/bash
。如果您总是要对单个脚本使用相同的解释器,那么您可以在此处定义它,这样就不必在命令中定义它。使用 shebang 来定义您不想用于该脚本的解释器是没有意义的。
我真的不明白为什么一个扩展比另一个更危险,或者你怎么会不小心输入所有这些。如果你使用制表符补全,任何一个扩展都会自动完成,所以这并不能防止笨拙。扩展很有用,这样你就可以识别/记住它是什么类型的文件。
无论如何,脚本的名称无关紧要。它甚至不需要扩展名。
有一个很好的问题Unix和Linux有更多相关信息。
答案3
如果在命令行中输入了设置了执行权限位的文件的名称,或者将此类文件的名称传递给 C 运行时库的 exec*() 变体调用之一,则 Linux 内核将尝试加载并执行它。
Linux 内核所做的第一件事是读取文件的前几个字节,寻找已知的“魔法”序列。其中一个魔法序列也可以解释为 ASCII 字符串“#!”,也称为“hash bang”,缩写为“shebang”。当加载器看到它时,它会将该行的其余部分解释为要执行的另一个文件的名称,并将第一个文件作为参数传递。另一个魔法值是“\x7fELF”,它是一个经典的二进制可执行文件,例如 /bin/sh 本身。请注意,如果文件没有可识别的魔法,内核加载器的默认设置是执行 /bin/sh 并将文件的名称作为第一个参数传递给它——相当于有一个“#!/bin/sh”的 shebang。
实际上,使用chmod +x ./do_one_thing.sh
“#!/bin/sh”将脚本标记为可执行文件相当于sh ./do_one_thing.sh
。“文件扩展名”或其他 DOS 概念在 DOS、其祖先操作系统(如 CP/M)及其后代操作系统(如 Microsoft Windows)之外实际上无关紧要。
如果您想要最高级别的万无一失,请将文件标记为可执行文件并使用适当的 shebang。不要依赖人类来做正确的事情。