我应该使用带Bash脚本的Shebang吗?

32 bash shell shebang sh

我正在使用Bash

$ echo $SHELL
/bin/bash
Run Code Online (Sandbox Code Playgroud)

从大约一年前开始,我停止使用Shebangs和我的Bash脚本.我可以使用#!/bin/sh或受益#!/bin/bash吗?

更新:在某些情况下,文件仅被视为Shebang的脚本示例

$ cat foo.sh
ls

$ cat bar.sh
#!/bin/sh
ls

$ file foo.sh bar.sh
foo.sh: ASCII text
bar.sh: POSIX shell script, ASCII text executable
Run Code Online (Sandbox Code Playgroud)

Rol*_*ith 41

在类UNIX系统上,您应该始终使用shebang行启动脚本.系统调用execve(负责启动程序)依赖于具有可执行标头或shebang线的可执行文件.

从FreeBSD的execve手册页:

 The execve() system call transforms the calling process into a new
 process.  The new process is constructed from an ordinary file, whose
 name is pointed to by path, called the new process file.
 [...]

 This file is
 either an executable object file, or a file of data for an interpreter.

 [...]

 An interpreter file begins with a line of the form:

       #! interpreter [arg]

 When an interpreter file is execve'd, the system actually execve's the
 specified interpreter.  If the optional arg is specified, it becomes the
 first argument to the interpreter, and the name of the originally
 execve'd file becomes the second argument
Run Code Online (Sandbox Code Playgroud)

同样来自Linux手册页:

execve()执行filename指向的程序.filename必须是二进制可执行文件,或者以表单行开头的脚本:

#! interpreter [optional-arg]
Run Code Online (Sandbox Code Playgroud)

实际上,如果文件的标题中没有正确的"幻数"(如ELF标题或者#!),execve则会因ENOEXEC错误而失败(再次来自FreeBSD的execve联机帮助页):

[ENOEXEC]新进程文件具有相应的访问权限,但标题中包含无效的幻数.


如果文件具有可执行权限,但没有shebang行但似乎确实是文本文件,则行为取决于您正在运行的shell.

大多数shell似乎开始自己的新实例并将其提供给文件,见下文.

由于无法保证脚本实际上是为该shell编写的,因此这可能会起作用或失败.

tcsh(1):

   On  systems which do not understand the `#!' script interpreter conven?
   tion the shell may be compiled to emulate it;  see  the  version  shell
   variable.  If so, the shell checks the first line of the file to see if
   it is of the form `#!interpreter arg ...'.  If it is, the shell  starts
   interpreter  with  the  given args and feeds the file to it on standard
   input.
Run Code Online (Sandbox Code Playgroud)

来自FreeBSD的sh(1):

If the program is not a normal executable file (i.e., if it
     does not begin with the “magic number” whose ASCII representation is
     “#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
     be a text file, the shell will run a new instance of sh to interpret it.
Run Code Online (Sandbox Code Playgroud)

来自bash(1):

   If this execution fails because the file is not in  executable  format,
   and  the file is not a directory, it is assumed to be a shell script, a
   file containing shell commands.  A subshell is spawned to  execute  it.
Run Code Online (Sandbox Code Playgroud)

您不能总是依赖于像bash这样的非标准程序的位置.我见过在bash /usr/bin,/usr/local/bin,/opt/fsf/bin/opt/gnu/bin仅举几例.

所以使用它通常是一个好主意env;

#!/usr/bin/env bash
Run Code Online (Sandbox Code Playgroud)

如果您希望脚本可移植,请使用sh而不是bash.

#!/bin/sh
Run Code Online (Sandbox Code Playgroud)

虽然像POSIX这样的标准并不能保证标准实用程序的绝对路径,但大多数类UNIX系统似乎都sh在内部/binenv外部/usr/bin.


Bar*_*mar 13

脚本应始终以shebang线开头.如果脚本没有以此开头,那么它可能由当前shell执行.但这意味着,如果使用您脚本的人运行的shell与您不同,则脚本的行为可能会有所不同.此外,这意味着脚本不能直接从程序运行(例如C exec()系统调用,或find -exec),它必须从shell运行.

  • 如果没有shebang,大多数(?)操作系统将尝试使用系统shell执行脚本. (2认同)
  • 没有shebang,脚本将由`/ bin/sh`执行,它可以是几个不同的类似Bourne的shell中的任何一个.例如,根据系统的不同,它可能是"dash","bash"或"ksh"的符号链接. (2认同)