适合傻瓜使用的 Bash Shebang?

适合傻瓜使用的 Bash Shebang?

我设置了一些 bash 脚本,主要使用

#!/bin/bash

但我经常遇到一些看起来像

#!/bin/bash -e
#!/bin/bash -x
#!/bin/bash -ex

等等。

有人可以解释一下这些 shebang 选项的含义和好处以及它们是否适用于其他 shebang 吗?

答案1

如果脚本/path/to/foo以 开头#!/bin/bash,则执行/path/to/foo arg1 arg2相当于执行/bin/bash /path/too/foo arg1 arg2。如果 shebang 行是#!/bin/bash -ex,则执行相当于执行/bin/bash -ex /path/too/foo arg1 arg2。此功能由内核管理。

请注意,您可以在 shebang 行上移植只有一个参数:一些 unices(例如 Linux)只接受一个参数,因此这#!/bin/bash -e -x会导致 bash 接收单个五个字符的参数-e -x(语法错误)而不是两个参数-e-x

对于 Bourne shellsh及其派生 shell,例如 POSIX sh、bash、ksh 和 zsh:

  • -e意味着如果任何命令失败(通过返回非零状态表示),脚本将立即终止。
  • -x导致 shell 打印执行跟踪。

其他程序可能理解这些选项,但含义不同。

答案2

它们是传递以bash查看help set更多信息的选项,在本例中为:

-x  Print commands and their arguments as they are executed.
-e  Exit immediately if a command exits with a non-zero status.

答案3

我只想提一个更好的(更便携的)替代方案:

#!/usr/bin/env bash

上面的例子使用env来查找bash可执行文件,但并不总是位于/bin/bash。旧的#!/bin/bash脚本无法在NixOS, 例如。

如果使用env如上所示的方式,则无法提供诸如-eto 之类的参数bash(据我所知)。但您可以改为这样做:

#!/usr/bin/env bash
set -e

答案4

使用 启动脚本,或者等效地运行 ,与在脚本中紧接着其行后插入具有相同的效果。#! /path/to/bash -optionbash -option /path/to/scriptset -option#!

set -x本质上只是为了调试;通常你不会希望它一直处于开启状态。

的效果set -e比手册上说的要复杂得多。更准确的描述大致如下:

调用后set -e,如果未经测试命令以非零状态退出,它将导致 shell 以该退出状态退出。

我说更确切因为它仍然很模糊:考虑该命令的情况列表已测试晦涩难懂,难以预测。确切的规则因 shell 而异,甚至同一 shell 的不同版本之间也存在差异。

set -e不是导致 Bash 因任何命令的非零退出状态而退出:

  • 之间if/elifthen; 或
  • 之间while/untildo; 或
  • 以下!;或
  • 随后是||&&&(尽管&相应的waitfg可能会失败);或
  • 随后是|,除非set -o pipefail有效;或
  • $( ... )当用作命令的一部分时位于内部(不是裸分配和/或重定向,这意味着foo=$( bar )如果失败将会失败bar,但local foo=$( bar )不会);或者
  • 在适用上述内容的复合命令中;或
  • 在从上述适用的任何地方调用的 shell 函数内部。

对复合命令和 shell 函数的影响是递归的。

由于壳层本身以非零状态退出,因此其效果可以传播出子壳层。

!即使忽略倒置退出状态,豁免仍然适用。

相反,set -e触发所有其他非零状态,无论它表示“失败”还是简单的“错误”。例如,当初始值为 0((x++))时,将具有非零“失败”退出状态。x

因为它太混乱了,所以有一派观点认为set -e应该避免这种情况,而应该明确检查所有命令。

或者如果您仍想使用set -e,请记住在任何组!前面写上。((arithmetic))

相关内容