|
最近用archlinux的pacman升级系统时,竟然无缘无故地报错,导致异常退出了。结果好多软件都升级一半就拉倒了。
典型的是升级binutils、kernel时出的问题:- warning: binutils-2.20-3 is up to date -- reinstalling
- resolving dependencies...
- looking for inter-conflicts...
- Targets (1): binutils-2.20-3
- Total Download Size: 0.00 MB
- Total Installed Size: 10.69 MB
- Proceed with installation? [Y/n]
- checking package integrity...
- (1/1) checking for file conflicts [#####################] 100%
- (1/1) upgrading binutils [#####################] 100%
- /tmp/alpm_E4acJi/.INSTALL: 2: Syntax error: "(" unexpected
- error: command failed to execute correctly
复制代码 升级kernel时,由于要使用mkinitcpio来制作modules,结果报出个Bad Substitution错误,然后直接退出了。
----------
这第二个错误看起来应该很明显,于是就从mkinitcpio脚本找问题的根源。。。。。。
看这个脚本老半天,还特意加了一些echo语句来测试。最终把问题定位在一个字符串处理上了:- ......
- if [ "${OPTARG:0:1}" = "-" ]; then
- ......
复制代码 把这句单提出来运行,也没有错误啊。于是又仔细研究了下这段代码,才猛然想起来,这个东西是bash才有的,在sh中是没有这种用法的……再看看文件的开头——赫然写着
#!/bin/sh
我才总算是明白过来,原来我的 /bin/sh 是直接链接到 /bin/dash 上了,而不是 /bin/bash 上。而这些shell脚本却“不守规矩”,在sh里加bash的语法导致的。于是乎,马上把/bin/sh改到/bin/bash上,再重装一下这些“问题软件”——全部顺利通过~
我想,其实要把这样的bash语法转化成更加可移植的sh,是不难的。比如上边提到的这段,个人感觉可以写成这样:- if [ "${OPTARG#-}" != "${OPTARG}" ]; then
- ####或者
- if [ -z "${OPTARG##-*}" ]; then
复制代码 嗯——从sh开始应该就有这样的变量替换了,反正这样写,dash就肯定可以处理了。
最后,为了看到问题的究竟,就到www.archlinux.org上,看了下bug列表http://bugs.archlinux.org/task/1 ... ;project=1&type,还真找到关于/bin/sh链接到/bin/dash后产生的问题的bug。显然一些人还在为解决这个问题而努力。
==========
现在看来ubuntu在这方面做的也许是比较好的了。其它的发行版本里,青一色的是sh->bash,记得之前觉得bash太大,我自己特意把fedora里的sh指向dash。结果问题非常严重:连系统启动都卡住了。
真希望以后linux界的shell脚本能保持linux本身的POSIX特点。如果一定要在脚本里写bash代码,为什么不把脚本的类型改为bash呢(#!/bin/bash)? |
|