【问题标题】:How to know what script header to use and why it matters?如何知道要使用什么脚本头以及它为什么重要?
【发布时间】:2014-02-12 15:41:10
【问题描述】:

我很少需要为各种不相关的目的编写 bash 脚本,虽然我通常很清楚我想要在脚本中使用什么命令,但我经常不知道要使用什么标头,或者当我找到时我为什么要使用一个标头它。例如:

  • 标准外壳脚本:
    • #!/bin/bash
  • 蟒蛇:
    • #!/usr/bin/env python

脚本似乎在没有标题的情况下也能正常工作,但如果标题是标准,那么它们是有原因的,它们不应该被忽略。如果它有效果,那么它就是一个有价值的工具,可以用来完成更多工作。

至少,我想知道 MySQL 脚本要使用哪些标头,以及标头在 Standard、Python 和 MySQL 脚本中的作用。理想情况下,我想要一个通用的标头列表或了解如何根据正在使用的程序创建标头。

【问题讨论】:

标签: linux bash shell scripting


【解决方案1】:

内核如何执行事情

简化(有点),POSIX 系统中的内核有两种方式知道如何执行程序。一,如果程序是内核理解的二进制格式(例如ELF),内核可以“直接”执行它(更多细节超出范围)。如果程序是以shebang开头的文本文件,比如

#!/usr/bin/somebinary -arg

或者你有什么,内核实际上执行命令就好像它被指示执行:

/usr/bin/somebinary -arg "$0"

其中$0 是您刚刚尝试执行的脚本文件的名称。 (所以你可以立即知道为什么这么多脚本语言使用# 作为注释启动器——这意味着它们不必将shebang 视为特殊。)

PATH 和 env 命令

内核不会查看 PATH 环境变量来确定您正在谈论的可执行文件,因此如果您将 python 脚本分发到可能安装了多个 python 版本的系统,您不能保证会有做一个

#!/usr/bin/python
然而,

envPOSIX,所以你可以指望它存在,it 会在 PATH 中查找 python。因此,

#!/usr/bin/env python

将使用 PATH 中找到的第一个 python 执行脚本。

BASH、SH 和调用的特殊含义

一些程序对于如何调用它们有特殊的语义。特别是,在许多系统上,/bin/sh 是指向另一个 shell 的符号链接,例如 /bin/bash。虽然 bash 不包含 sh 的完美 POSIXLY_STRICT 实现,但当它以 /bin/sh 调用时,它比以 plain-old-bash 调用时要更严格

MySQL 和 arg 限制

shebang 行有长度限制,从技术上讲,它只能支持一个参数,所以 mysql 有点棘手——你不能指望将用户名和数据库名称传递给 mysql 脚本。

#!/usr/bin/env mysql
use mydb;
select * from mytbl;

将失败,因为内核将尝试mysql "$0"。即使您在.my.cnf 文件中有您的凭据,mysql 本身也会尝试将“$0”视为数据库名称。同样:

#!/usr/bin/mysql -e
use mydb;
select * from mytbl;

将再次失败,因为“$0”不是表名(您希望如此)。

以这种方式直接执行 mysql 脚本似乎没有合适的语法。最好的办法是将 sql 命令直接通过管道传输到 mysql:

mysql < my_sql_commands

【讨论】:

    【解决方案2】:

    http://mywiki.wooledge.org/BashGuide/Practices#Choose_Your_Shell

    当脚本的第一行以#! 开头时,这就是所谓的“shebang”。当该脚本作为可执行文件运行时,操作系统使用该行来确定如何运行该脚本——也就是说,找到应该执行该脚本的程序。

    “脚本在没有标题的情况下也能正常工作”是不正确的——如果您没有 shebang 行,则无法使用 execve() 调用来调用您,这意味着许多(大多数?)程序不会能够执行你的脚本。有时从 shell 调用会在没有 shebang 的情况下尝试使用该 shell 本身,但您不能相信会是这种情况。

    (有一个例外——如果有人通过运行sh yourscriptbash yourscript 来启动您的脚本,则根本不会读取shebang 行,而是使用他们选择的脚本;但是,以这种方式运行脚本是一种不好的做法,因为作者通常比用户更了解正确的解释器是什么)。

    简而言之:

    • 如果您想使用现代功能,并且希望用户能够通过在其路径中更早地放置不同版本的 bash 来覆盖正在使用的 shell 版本,请使用 #!/usr/bin/env bash
    • 如果您想使用现代功能并确保始终使用系统 shell 运行,请使用 #!/bin/bash
    • 如果您要编写脚本以严格遵守 POSIX sh,请使用 #!/bin/sh

    我们可以为您提供的 shebang 行的列表并不有限,因为任何本机可执行文件(非脚本程序)都可以用作脚本解释器,因此可以放置在 shebang 中。如果您使用#!/usr/bin/env yourprogram 创建了一个名为myscript 的文件,赋予它可执行权限,然后运行./myscript foo bar,这将导致/usr/bin/env yourprogram myscript foo bar 被调用; yourprogram 将由 /usr/bin/env 运行(在 PATH 查找之后),并负责了解如何处理 myscript 及其参数。

    有关 shebang 线的极其详细的历史以及它们如何在现代和古代系统中工作,请参阅 http://www.in-ulm.de/~mascheck/various/shebang/

    【讨论】:

    • 作者通常比用户更了解...... 尽管作者将 bashisms 放在 /bin/sh 脚本中。 :)
    猜你喜欢
    • 2021-05-11
    • 2022-01-22
    • 2012-04-26
    • 2011-10-22
    • 2016-10-26
    • 1970-01-01
    • 2020-10-25
    • 2016-09-17
    • 2014-06-01
    相关资源
    最近更新 更多