什么是首选的Bash sheband(“#!”)?

在大多数用途上,有没有任何Bash sheband客观上比其他人更好?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -

我依稀记得很久以前听说在末尾添加破折号可以防止有人向您的脚本传递命令,但找不到任何细节。

609412 次浏览

/bin/sh通常是指向系统默认shell的链接,通常是bash但打开,例如,Debian系统是重量较轻的dash。无论哪种方式,最初的Bourne shell是sh,所以如果你的脚本使用了一些bash(第二代,“Bourne再次sh”)的特定功能([[ ]]测试,数组,各种含糖的东西,等等),那么你应该更具体,使用后者。这样,在未安装bash的系统上,你的脚本将无法运行。我知道关于这种演变可能会有一个令人兴奋的电影三部曲……但这可能是道听途说。

还要注意,当被唤起为sh时,bash在某种程度上是符合POSIX标准sh(另见的GNU文档)。

这实际上取决于您如何编写bash脚本。如果您的/bin/sh符号链接到bash,当bash作为sh某些功能不可用调用时。

如果您想要bash特定的非POSIX功能,请使用#!/bin/bash

你应该在可移植性中使用#0:不同的*nix将bash放在不同的位置,使用/usr/bin/env是一种解决方法,可以运行在PATH上找到的第一个bash。和#5不是#1

使用sheband行调用适当的解释器不仅仅适用于BASH。您可以将sheband用于系统上的任何解释语言,例如Perl、Python、PHP(CLI)和许多其他语言。顺便说一句,sheband

#!/bin/sh -

(它也可以是两个破折号,即--)结束bash选项之后的所有内容都将被视为文件名和参数。

使用env命令使您的脚本可移植,并允许您为脚本设置自定义环境,因此可移植脚本应该使用

#!/usr/bin/env bash

或者对于任何语言,例如Perl

#!/usr/bin/env perl

请务必查看bashman页面:

man bash

env

man env

注意:在Debian和基于Debian的系统上,如Ubuntu,sh链接到dash而不是bash。由于所有系统脚本都使用sh。根据Debian的说法,这允许bash增长并保持系统稳定。

此外,为了保持调用*nix,就像我从不在sheang调用的脚本上使用文件扩展名一样,因为您不能像在Windows上那样在调用可执行文件时省略扩展名。文件命令可以将其识别为脚本。

我建议使用:

#!/bin/bash

它不是100%可移植的(有些系统将bash放在/bin以外的位置),但许多现有脚本使用#!/bin/bash的事实迫使各种操作系统至少将/bin/bash作为指向主位置的符号链接。

替代办法:

#!/usr/bin/env bash

已经有人建议--但是不能保证env命令在/usr/bin中(我也使用过不在/usr/bin中的系统)。此外,此表单将在当前用户$PATH中使用bash的第一个实例,这可能不是bash shell的合适版本。

(但是/usr/bin/env应该适用于任何合理的现代系统,要么是因为env/usr/bin中,要么是因为系统做了一些事情使其工作。我上面提到的系统是SunOS 4,我可能已经25年没有使用过了。)

如果您需要在没有/bin/bash的系统上运行脚本,您可以修改脚本以指向正确的位置(这确实不方便)。

我在我的答案这个问题中更深入地讨论了权衡。

一个有点模糊的更新:我使用的一个系统,Termux,一个在Android下运行的桌面Linux层,没有/bin/bashbash/data/data/com.termux/files/usr/bin/bash)-但它有特殊的处理来支持#!/bin/bash

#!/bin/sh

因为大多数脚本不需要特定的bash功能,应该为sh编写。

此外,这使得脚本可以在BSD上工作,BSD默认情况下没有bash。

在#! /usr/bin/env方法中再添加一票。我经常使用虚拟环境,在我的情况下,我使用安装在虚拟环境中的python。使用#! /usr/bin/python可能不是我想要的python。我使用#!得到正确的python! /usr/bin/envpython。