我正在使用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手册页:
Run Code Online (Sandbox Code Playgroud)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
同样来自Linux手册页:
execve()执行filename指向的程序.filename必须是二进制可执行文件,或者以表单行开头的脚本:
Run Code Online (Sandbox Code Playgroud)#! interpreter [optional-arg]
实际上,如果文件的标题中没有正确的"幻数"(如ELF标题或者#!),execve则会因ENOEXEC错误而失败(再次来自FreeBSD的execve联机帮助页):
[ENOEXEC]新进程文件具有相应的访问权限,但标题中包含无效的幻数.
如果文件具有可执行权限,但没有shebang行但似乎确实是文本文件,则行为取决于您正在运行的shell.
大多数shell似乎开始自己的新实例并将其提供给文件,见下文.
由于无法保证脚本实际上是为该shell编写的,因此这可能会起作用或失败.
从tcsh(1):
Run Code Online (Sandbox Code Playgroud)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.
来自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):
Run Code Online (Sandbox Code Playgroud)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.
您不能总是依赖于像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在内部/bin和env外部/usr/bin.
Bar*_*mar 13
脚本应始终以shebang线开头.如果脚本没有以此开头,那么它可能由当前shell执行.但这意味着,如果使用您脚本的人运行的shell与您不同,则脚本的行为可能会有所不同.此外,这意味着脚本不能直接从程序运行(例如C exec()系统调用,或find -exec),它必须从shell运行.