当前位置: 首页>>技术教程>>正文


解释器是否读取了#!/bin/sh?

, , ,

问题描述

bashsh中,我猜任何以#开头的都是评论。

但是在bash脚本中我们写道:

#!/bin/bash

在Python脚本中,有:

#!/bin/python

这是否意味着#本身是评论而#!不是?

最佳解决方案

在脚本运行之前使用#!行,然后在脚本运行时忽略。

你问的是shebang line和普通评论之间有什么区别。

#!开头的行与使用#开头的任何其他行一样多。如果#!是文件的第一行或其他任何位置,则为true。 #!/bin/sh有效,但解释器本身无法读取。

#不是所有编程语言中的注释,但是,如您所知,它是Bourne-style shell中的注释,包括shbash(以及大多数non-Bourne-style shell,如csh)。这是also a comment in Python。它是各种配置文件中的注释,根本不是脚本(如/etc/fstab)。

假设shell脚本以#!/bin/sh开头。这是一个注释,解释器(shell)忽略#字符后面的所有内容。

#!行的目的不是为解释器提供信息。 #!系列的目的是告诉操作系统(或任何进程启动解释器)使用什么作为解释器。

  • 如果您将脚本作为可执行文件调用,例如,通过运行./script.sh,系统将查询第一行,以查看是以#!开头,后跟零个或多个空格,后跟命令。如果是,则运行该命令,并将脚本名称作为其参数。在此示例中,它运行/bin/sh script.sh(或技术上,/bin/sh ./script.sh)。

  • 如果通过显式调用解释器来调用脚本,则永远不会查询#!行。因此,如果您运行sh script.sh,则第一行无效。如果script2.sh的第一行是#!/usr/games/nibbles,则运行sh script2.sh将不会尝试在nibbles(但./script2.sh)中打开脚本。

您会注意到,在任何情况下,脚本的扩展名(.sh)(如果有)都会影响它的运行方式。在Unix-like系统中,这通常不会影响脚本的运行方式。在某些其他系统(如Windows)上,系统可能会完全忽略#! shebang行,并且扩展可能会确定运行脚本的内容。 (这并不意味着您需要提供脚本扩展,但这是其中一个原因,如果您这样做,它们应该是正确的。)

选择#!是为了达到这个目的,因为#开始发表评论。 #!行用于系统,而不是解释器,解释器应该忽略它。

Shebang Line for Bash Scripts

您(最初)说您使用#!/bin/sh用于bash脚本。只有在脚本不需要任何bash扩展时才应该这样做 – sh需要能够运行脚本。 sh并不总是bash的符号链接。通常,包括在所有最近的Debian和Ubuntu系统上,shdash的符号链接。

Shebang Line for Python Scripts

您还说(在编辑之前的第一个版本中)您使用#!/bin/sh read by the interpretor启动Python脚本。如果你的意思是字面意思,那么你绝对应该停止这样做。如果hello.py以该行开头,则运行./hello.py执行:

/bin/sh read by the interpretor hello.py

/bin/sh将尝试执行一个名为read的脚本(以by the interpretor hello.py为参数),read将(希望)找不到,Python解释器永远不会看到你的Python脚本。

如果你犯了这个错误但没有我正在描述的问题,你可能通过明确指定解释器(例如,python hello.py)来调用你的Python程序,导致第一行被忽略。当您将脚本分发给其他人,或者很久以后使用它们时,可能并不清楚这对他们来说是必要的。现在最好修复它们。或者至少完全删除第一行,这样当它们无法使用./运行时,错误消息才有意义。

对于Python脚本,如果您知道Python解释器(或将要)的位置,您可以使用相同的方式编写#!行:

#!/usr/bin/python

或者,如果它是Python 3脚本,则应指定python3,因为python几乎总是Python 2:

#!/usr/bin/python3

然而,问题是虽然/bin/sh应该始终存在,并且/bin/bash几乎总是存在于bash随操作系统附带的系统上,但Python可能存在于各种各样的地方。

因此,许多Python程序员使用它代替:

#!/usr/bin/env python

(或者Python 3的#!/usr/bin/env python3)

这使得脚本依赖于env在”right place”中而不是依赖于python在正确的位置。这是件好事,因为:

  • env几乎总是位于/usr/bin中。

  • 在大多数系统上,无论哪个python运行您的脚本都是首先出现在PATH中的脚本。用#!/usr/bin/env python开始hello.py使./hello.py运行/usr/bin/env python hello.py,其(实际上)等同于运行python hello.py

你不能使用#!python的原因是:

  • 您希望指定的解释器由绝对路径给出(即,从/开始)。

  • 调用进程将在当前目录中执行python。当命令不包含斜杠时搜索路径的行为是特定的shell行为。

有时,Python或其他不是shell脚本的脚本将有一个以#!/bin/sh ...开头的shebang行,其中...是其他一些代码。这有时是正确的,因为有一些方法可以使用参数调用Bourne-compatible shell(sh)以使其调用Python解释器。 (其中一个参数可能包含python。)但是,对于大多数用途,#!/usr/bin/env python更简单,更优雅,更有可能以您想要的方式工作。

Shebang Lines in Other Languages

许多编程和脚本语言以及一些其他文件格式使用#作为注释。对于它们中的任何一个,语言中的文件可以由程序运行,该程序通过在#!之后的第一行指定程序将其作为参数。

在某些编程语言中,#通常不是注释,但作为特殊情况,如果第一行以#!开头,则忽略第一行。这有助于使用#!语法,即使#不以其他方式发表评论。

Shebang为不运行脚本的文件行

虽然它不太直观,但任何文件格式都可以容纳以#!开头的第一行的文件后跟可执行文件的完整路径都可以有一个shebang行。如果你这样做,并且文件被标记为可执行文件,那么你可以像程序一样运行它……使它像文档一样打开。

某些应用程序故意使用此行为。例如,在VMware中,.vmx文件定义虚拟机。您可以将”run”虚拟机视为一个脚本,因为这些文件标记为可执行文件,并且有一个shebang行,导致它们在VMware实用程序中打开。

Shebang为那些不像脚本运行但是像脚本一样的文件

rm删除文件。它不是脚本语言。但是,可以运行启动#!/bin/rm并标记为可执行文件的文件,并在运行它时,在其上调用rm,将其删除。

这通常被概念化为“文件删除自身”。但该文件根本没有运行。这更像是上面描述的.vmx文件的情况。

但是,由于#!行有助于运行简单命令(包括命令行参数),因此您可以通过这种方式执行某些脚本。作为比#!/bin/rm更复杂的”script”的简单示例,请考虑:

#!/usr/bin/env tee -a

这会以交互方式接收用户输入,将其回送给用户line-by-line,并将其附加到”script”文件的末尾。

有用?不是特别的。概念上有趣吗?完全!是。 (有些。)

概念上类似的编程/脚本概念(只是为了好玩)

次佳解决方案

一个shebang是由字符编号和感叹号(例如”#!”)组成的字符序列,当它作为脚本初始行的最初两个字符出现时。

在* nix操作系统下,当运行以shebang开头的脚本时,程序加载器将脚本初始行的其余部分解析为解释器指令;而是运行指定的解释器程序,将其作为参数传递给尝试运行脚本时最初使用的路径。例如,如果脚本以路径”path/to/your-script”命名,并且它以以下行开头:

#!/bin/sh

然后指示程序加载程序运行程序”/bin/sh”,例如, Bourne shell或兼容shell,将”path/to/your-script”作为第一个参数传递。

因此,脚本以路径”path/to/python-script”命名,并从以下行开始:

#!/bin/python

然后指示加载的程序运行程序”/bin/python”,例如, Python解释器,将”path/to/python-script”作为第一个参数传递。

简而言之,”#”将注释掉一行,而作为脚本初始行的前两个字符出现的字符序列”#!”具有如上所述的含义。

有关详细信息,请参阅Why do some scripts start with #! … ?

来源:这个答案的某些部分来自英语维基百科上的Shebang(Unix)(由维基百科贡献者提供)。本文根据CC-BY-SA 3.0进行许可,与AU上的用户内容相同,因此允许使用归属进行推导。

第三种解决方案

#!作为脚本初始行的前两个字符出现时,它被称为shebang。它在脚本中用于指示要执行的解释器。 shebang用于操作系统(内核),不用于shell;所以它不会被解释为评论。

礼貌:http://en.wikipedia.org/wiki/Shebang_%28Unix%29

In general, if a file is executable, but actually not an executable (binary) program, and such a line is present, the program specified after #! is started with the scriptname and all its arguments. These two characters # and ! have to be the first two bytes in the file!

详细信息:http://wiki.bash-hackers.org/scripting/basics#the_shebang

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/1240.html,未经允许,请勿转载。