我通常使用Ubuntu服务器,据我所理解,这些服务器可以将/bin/sh
链接到/bin/dash
。很多其他发行版都是通过符号链接/bin/sh
到/bin/bash
的。
由此我了解到,如果脚本在顶部使用#!/bin/sh
,那么它可能不会在所有服务器上以相同的方式运行?
当您想要在服务器之间最大限度地实现脚本的可移植性时,是否建议在脚本上使用哪个shell?
发布于 2017-07-30 06:37:14
shell脚本大约有四个级别的可移植性(就shebang行而言):
#!/bin/sh
shebang,并且只使用POSIX标准中指定的基本shell语法。这应该适用于几乎所有的POSIX/unix/linux系统。(好吧,除了Solaris 10和更早版本,它有真正的遗留Bourne,在POSIX之前就已经不兼容了,比如/bin/sh
。)#!/bin/bash
(或#!/usr/bin/env bash
) shebang行,并坚持bash v3特性。这将适用于任何具有bash (在预期位置)的系统。#!/bin/bash
(或#!/usr/bin/env bash
) shebang行,并使用bash v4特性。这在任何具有bash v3的系统上都会失败(例如,由于许可原因,macOS必须使用它)。#!/bin/sh
shebang,并使用POSIX语法的bash扩展。这在任何系统上都会失败,而不是bashfor/bin/sh(例如最近的Ubuntu版本)。永远不要这样做;这不仅仅是一个兼容性问题,它是完全错误的。不幸的是,这是很多人都会犯的错误。我的建议是:使用前三项中最保守的一项,它提供脚本所需的所有shell功能。对于最大可移植性,请使用选项#1,但根据我的经验,一些bash特性(如数组)非常有用,因此我将使用#2。
你能做的最糟糕的事情是#4,使用错误的弹出声。如果您不确定哪些特性是基本的POSIX,哪些是bash扩展,那么要么坚持bash shebang (即选项2),要么使用非常基本的shell彻底测试脚本(比如Ubuntu服务器上的破折号)。Ubuntu有一个值得注意的好的羞耻感清单。
关于unix&linux问题“与sh兼容意味着什么?”中的shell和堆栈溢出问题“sh和bash的区别”中的shell之间的历史和差异,有一些非常好的信息。
另外,要注意的是,shell并不是不同系统之间唯一不同的地方;如果您习惯了linux,那么您就习惯了GNU命令,这些命令在其他unix系统(如bsd、macOS)上可能找不到很多不标准的扩展。不幸的是,这里没有简单的规则,您只需知道所使用的命令的变化范围。
在可移植性方面,最讨厌的命令之一是最基本的命令之一:echo
。任何时候,当您将它与任何选项(例如echo -n
或echo -e
)或字符串中的任何转义符(反斜杠)一起使用以打印时,不同的版本将执行不同的操作。任何时候,如果您想要在字符串后面打印没有行提要的字符串,或者在字符串中使用转义符,请使用printf
(并学习它是如何工作的--它比echo
更复杂)。ps
命令是也是一塌糊涂。
另一个常用的方法是命令选项语法的最近/GNUish扩展:旧(标准)命令格式是命令后面跟着选项(带有单个破折号,每个选项是一个字母),后面跟着命令参数。最近的(通常也是不可移植的)变体包括长选项(通常与--
一起引入),允许选项在参数之后出现,并使用--
将选项从参数中分离出来。
https://serverfault.com/questions/865874
复制相似问题