0. 前言

某次编写完脚本,本地测试通过后,部署到服务器中,运行至该脚本(sh xxx.sh)时,发现运行报错Syntax error: “(” unexpected when creating an array,脚本错误行内容如下所示:

1
2
3
4
5
#!/bin/sh
...
## 下行为错误行
TB=(${TB//:/ })
...

可见该行执行的是进行字符串分割为数组的功能

a. 原因

经查询资料后发现,这是因为由于shbash照成的差异, sh不支持创建数组 ,但作为sh的增强版——bash可以,实际上执行脚本的时候会根据脚本文件首行进行执行器的选择,即首行的#!/bin/sh,但当使用sh xxx.sh执行时,将会执行sh而不是bash。而此处使用的是sh,而上述造成错误的语句则是bash里的增强功能,因而导致脚本执行失败。

b. 解决

实际上解决方法很简单,使用了bash里的特有语句,即将脚本首行#!/bin/sh更改为#!/bin/bash同时将执行指令更改为bash xxx.sh即可正常执行脚本文件。

1. What is sh

sh(Shell Command Language)是一种根据POSIX(Portable Operating System Interface)标准而生成的编程语言 (ksh88,dash等语言都是基于此标准接口实现出来的) ,现在大多用sh来编写脚本文件。

同时因为sh是规范而不是实现,所以/bin/sh是大多数POSIX系统上实现的符号链接,通俗地说就是一个链接的映射,如同Windows中的快捷方式。

2. What is bash

bash是一种兼容sh的实现方式(尽管bash早于POSIX标准诞生),但随着时间bash也通过sh获得了许多的扩展,而这些增强扩展是以POSIX标准Shell脚本形式加入的,因此bash本身并不是一个标准POSIX形式的Shell,反过来说它更像是POSIX形式的Shell语言的一种方言。

bash同时也是大多数Linux系统以及Mac OS X默认使用的Shell,它可以运行在大多数Unix风格的操作系统之上,甚至被移植到了Microsoft Windows上的Cygwin系统中(参考Windows Git Bash),以实现Windows的POSIX虚拟接口。

3. 历史

由于理查德·斯托曼(由软件运动的精神领袖、GNU计划以及自由软件基金会(Free Software Foundation)的创立者、著名黑客)对于之前一位开发者的进度不满,布莱恩·福克斯从1988年1月10日开始开发Bash。斯托曼和自由软件基金会希望到一个能够运行已有的shell脚本的自由软件。他们把这看作是建成一个基于BSD和GNU的完全自由的操作系统的战略的重要部分。这是他们自己注资的几个项目之一。福克斯作为自由软件基金会的雇员承担了这项工作。1989年6月8日,福克斯发布了Bash的beta版本,版本号为.99。在福克斯离开于1992年中期到1994年中期的某个时候离开自由软件基金会之前,他一直担任Bash的主要维护者。之后,他的工作被传递给另一个早期贡献者,切特·雷米(Chet Ramey)。

从那时起,在Linux用户当中sh在很大度上成为了最流行的shell,并成为许多Linux发行版默认的交互式shell(不过Almquist shell可能是默认的脚本shell)。在苹果公司的 OS X 操作系统上也是如此。Bash 也被移植到 Microsoft Windows(通过Cygwin和MinGW)。通过DJGPP项目,Bash被移植到了DOS。通过许多终端模拟软件,Bash被移植到Novell NetWare和Android。微软在2016年的Build大会上宣布,Windows 10 添加了一个Linux子系统,完全支持Bash和其他Ubuntu下的二进制程序。

2014年9月24日,Stephane Chazelas,一位工作于英国,致力于Unix/Linux和网络通信方面的专家,发现了Bash的一个安全漏洞。这个漏洞被命名为Shellshock,并被分配了编号 CVE-2014-6271、CVE-2014-6277、CVE-2014-7169。这个漏洞非常严重,因为使用Bash的CGI脚本会变得脆弱,使得攻击者可以执行任意的代码。这个漏洞与Bash通过环境变量把函数定义传递给shell子进程的方式有关。