使用 #!/bin/sh 或 #!/bin/bash 以获得 Ubuntu-OSX 兼容性和易用性和 POSIX

Mic*_*ant 18 osx shell bash ubuntu posix

我知道我可以使用任一脚本作为调用所需 shell 的第一行。

#!/bin/sh如果与所有 unix 系统的兼容性是绝对要求,会推荐吗?

就我而言,我唯一关心的操作系统是 Ubuntu (Debian) 和 OSX。鉴于此,我可以使用#!/bin/bash并确保它可以在两个系统上运行吗?
这是否也可以更轻松地使用具有更现代和更清晰的命令语法的脚本?使用是否#!/bin/sh也与使用 POSIX 有关?

0xC*_*22L 15

首先,如果您可以假设 Bash 是预装的(据我所知,您列出的所有系统都是这种情况),请使用以下 hashbang 来兼容:

#!/usr/bin/env bash
Run Code Online (Sandbox Code Playgroud)

这会调用bash发生的任何配置,无论它是 in/bin还是/usr/local/bin.

虽然在范围广泛的大多数系统(包括 AIX、Solaris、几种 BSD 风格)上,bash最终出现在不同的位置,但env最终总是以/usr/bin/env. 然而,诀窍不是我的,而是来自 Bash Cookbook 的作者。

无论如何,是的,Bash 将允许您使用一些“现代”功能,让您的生活更轻松。

例如双括号:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"
Run Code Online (Sandbox Code Playgroud)

而在传统的贝壳方言中,您必须求助于:

test -f "/etc/debian_version" && echo "This is a Debian flavor"
Run Code Online (Sandbox Code Playgroud)

但双括号最好的地方在于它们允许使用正则表达式进行匹配。该猛砸黑客维基会给你很多的技巧在那个方向。

您还可以使用非常方便的表达式,例如$((2**10))或其他与$((expression))语法内联的算术表达式。

对 subshel​​l 使用反引号很好,尽管有点过时。但是$(command ...)调用的嵌套功能更方便,因为您不必在不同的子 shell 级别逃避许多事情。

这些只是 Bash 在传统常见 POSIXsh语法上为您提供的一些东西。

但是如果你想在 shell 上获得更多的力量(不仅仅是在脚本中),也可以看看zsh.


Ste*_*itt 11

在 Debian 和 Ubuntu 中,/bin/shis dash,这是一个符合 POSIX 的 shell。如果指定#!/bin/sh,则必须将自己限制为脚本中的 POSIX 语句。(优点是dash启动速度比 快bash,因此您的脚本可以在更短的时间内完成其工作。)

在许多(大多数?)其他 Linux 系统上,/bin/shis bash,这就是为什么许多脚本编写#!/bin/sh为它们的 shebang 行,即使它们使用bash扩展名。

如果要使用bash扩展,在所有系统上最安全的方法是指定#!/bin/bash; 这样你就明确说明了你对bash. 您需要在 Debian 和 Ubuntu 上执行此操作。作为一个额外的好处,当作为开始/bin/sh bash去激活一些扩展(见的描述bashPOSIX模式的详细信息); 因此#!/bin/bash必须指定才能获得bash.

在 OS X 上/bin/bash也可用,并且/bin/shbash. 指定#!/bin/bash在那里也能正常工作。


ter*_*don 5

是的,OSX 和 Linux 都会附带/bin/bash. 你应该是完全安全的。但是,这不是POSIX。POSIX shell 是在/bin/sh大多数(所有?)系统上,这是最便携的方法,也是与 POSIX 兼容的唯一方法。

请注意,虽然在许多系统上/bin/sh指向bash,但在其他系统上它可以指向不同的外壳。例如,它是dashDebian 和 Ubuntu 上的符号链接。此外,即使/bin/sh是到 的链接bash,shell 的行为在被调用时也会发生变化sh(来自man bash,重点是我的):

如果使用名称 sh 调用 bash,它会尝试尽可能模仿 sh 历史版本的启动行为,同时也符合 POSIX 标准。 当作为交互调用时?tive 登录 shell,或带有 --login 选项的非交互式 shell,它首先尝试从 /etc/profile 和 ~/.profile 中按顺序读取和执行命令。--noprofile 选项可用于禁止此行为。当作为一个名为 sh 的交互式 shell 调用时,bash 查找变量 ENV,如果它是,则扩展它的值
定义,并使用扩展值作为要读取和执行的文件名。由于作为 sh 调用的 shell 不会尝试从任何其他启动文件读取和执行命令,因此 --rcfile 选项无效。 使用名称 sh 调用的非交互式 shell 不会尝试读取任何其他启动文件。当作为 sh 调用时,bash 在读取启动文件后进入 posix 模式。