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


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

, , , ,

问题描述

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

如果绝对需要与所有unix系统兼容,那么会建议使用#!/bin/sh吗?

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

最佳方法

对于初学者,如果您可以假设已预先安装Bash(据我所知,您列出的所有系统都是这种情况),请使用以下hashbang进行兼容:

#!/usr/bin/env bash

无论是/bin还是/usr/local/bin,这都会调用恰好要配置的bash

在范围广泛的大多数系统(包括AIX,Solaris和几种BSD版本)上,bash最终出现在不同的位置,而env总是最终出现在/usr/bin/env。但是,诀窍不是我的,而是Bash Cookbook的作者。

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

例如,双括号:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

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

test -f "/etc/debian_version" && echo "This is a Debian flavor"

但是关于双括号的最好之处在于它们允许使用正则表达式进行匹配。 Bash Hackers Wiki将为您提供许多朝此方向的技巧。

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

对子壳使用反引号也可以,尽管有些过时了。但是$(command ...)调用的嵌套功能更加方便,因为您不必在不同的子Shell级别上转义许多内容。

这些只是Bash在传统的通用PO​​SIX sh语法之上为您提供的一些内容。

但是,如果您想在shell上拥有更多功能(不仅是在脚本中),还可以看看zsh

次佳方法

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

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

如果要使用bash扩展名,则在所有系统上最安全的方法是指定#!/bin/bash;这样,您将明确声明对bash的依赖性。您需要在Debian和Ubuntu上执行此操作。另外,在以/bin/sh bash de-activates身份启动时,有一些扩展(有关详细信息,请参见bash POSIX模式的描述);因此必须指定#!/bin/bash才能获得bash的全部好处。

在OS X上,/bin/bash也可用,而/bin/shbash。指定#!/bin/bash在那里也可以正常工作。

第三种方法

是的,OSX和Linux都将随附/bin/bash。您应该完全安全。但是,那不是POSIX。 POSIX shell 在大多数(所有)系统上的位置为/bin/sh,这是最可移植的方法,也是唯一兼容POSIX的方法。

请注意,尽管在许多系统上/bin/sh指向bash,但在其他系统上它却可以指向不同的 shell 。例如,这是在Debian和Ubuntu上与dash的符号链接。同样,即使/bin/sh是到bash的链接,当它被称为sh(来自man bash,重点是我的)时,shell的行为也会改变:

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interac‐ tive login shell, or a non-interactive shell with the –login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The –noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is
defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the –rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, bash enters posix mode after the startup files are read.

参考资料

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