LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1431|回复: 9

由archlinux升级出错而感慨“sh->bash”的问题

[复制链接]
发表于 2010-1-1 23:42:14 | 显示全部楼层 |阅读模式
最近用archlinux的pacman升级系统时,竟然无缘无故地报错,导致异常退出了。结果好多软件都升级一半就拉倒了。
典型的是升级binutils、kernel时出的问题:
  1. warning: binutils-2.20-3 is up to date -- reinstalling
  2. resolving dependencies...
  3. looking for inter-conflicts...
  4. Targets (1): binutils-2.20-3
  5. Total Download Size:    0.00 MB
  6. Total Installed Size:   10.69 MB
  7. Proceed with installation? [Y/n]
  8. checking package integrity...
  9. (1/1) checking for file conflicts                   [#####################] 100%
  10. (1/1) upgrading binutils                            [#####################] 100%
  11. /tmp/alpm_E4acJi/.INSTALL: 2: Syntax error: "(" unexpected
  12. error: command failed to execute correctly
复制代码
升级kernel时,由于要使用mkinitcpio来制作modules,结果报出个Bad Substitution错误,然后直接退出了。
----------

这第二个错误看起来应该很明显,于是就从mkinitcpio脚本找问题的根源。。。。。。
看这个脚本老半天,还特意加了一些echo语句来测试。最终把问题定位在一个字符串处理上了:
  1. ......
  2. if [ "${OPTARG:0:1}" = "-" ]; then
  3. ......
复制代码
把这句单提出来运行,也没有错误啊。于是又仔细研究了下这段代码,才猛然想起来,这个东西是bash才有的,在sh中是没有这种用法的……再看看文件的开头——赫然写着
#!/bin/sh
我才总算是明白过来,原来我的 /bin/sh 是直接链接到 /bin/dash 上了,而不是 /bin/bash 上。而这些shell脚本却“不守规矩”,在sh里加bash的语法导致的。于是乎,马上把/bin/sh改到/bin/bash上,再重装一下这些“问题软件”——全部顺利通过~
我想,其实要把这样的bash语法转化成更加可移植的sh,是不难的。比如上边提到的这段,个人感觉可以写成这样:
  1. if [ "${OPTARG#-}" != "${OPTARG}" ]; then
  2. ####或者
  3. 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)?
发表于 2010-1-2 16:48:09 | 显示全部楼层
学习学习学习
回复 支持 反对

使用道具 举报

发表于 2010-1-2 22:14:56 | 显示全部楼层
这个问题我不是很懂,说点粗浅的看法,/bin/sh 似乎仅仅是启动时使用的,用户和 root 执行脚本用到的 shell 单独有定义,在 ubuntu 中默认还都是 bash。或者你把自己的 shell 设成了 /bin/sh ?
回复 支持 反对

使用道具 举报

发表于 2010-1-3 21:25:10 | 显示全部楼层
Post by AutoXBC;2061446
这个问题我不是很懂,说点粗浅的看法,/bin/sh 似乎仅仅是启动时使用的,用户和 root 执行脚本用到的 shell 单独有定义,在 ubuntu 中默认还都是 bash。或者你把自己的 shell 设成了 /bin/sh ?


人家是说很多脚本头上写着#!/bin/sh,但脚本中却用bash的特有语法。还有,ubuntu中/bin/sh默认链接是/bin/dash,不是bash!
回复 支持 反对

使用道具 举报

发表于 2010-1-3 22:51:43 | 显示全部楼层
我理解错了,不过楼上也没完全明白我的意思。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-1-4 22:06:00 | 显示全部楼层
……本以为把我对现实的想法写出来,可以引起大家的共鸣。原来有那么多人对sh、dash、bash、csh、tcsh都不了解……
……看来是我杞人忧天了。
回复 支持 反对

使用道具 举报

发表于 2010-1-6 02:07:33 | 显示全部楼层
这个没办法,几乎所有发行版的默认shell都是bash,而且不可能被卸载掉.(或许可以自己定制个没有bash的系统 )

大家写脚本都是用bash的语法吧,毕竟有更强大的功能和更多的扩展.

况且你如果要用其他的shell作为默认shell, 也完全不需要改动/bin/sh的链接目标.

至于为什么shebang都指定 /bin/sh,这个大概可以说是习惯,确实有不合理的地方.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-1-6 19:28:54 | 显示全部楼层
Post by qsdickee;2061710
人家是说很多脚本头上写着#!/bin/sh,但脚本中却用bash的特有语法。还有,ubuntu中/bin/sh默认链接是/bin/dash,不是bash!

还是qsdickee了解我的意思,看不懂楼上在说什么。
我得说明一下了。我的系统默认Shell就是bash,不是什么别的shell。
“系统默认Shell” 跟我的文字没有什么关系
回复 支持 反对

使用道具 举报

发表于 2010-1-7 01:16:04 | 显示全部楼层
这个还是兼容的问题。只不过linux的系统一般默认是bash,都是一个软链接。
但是要知道有些bash的语法在正规的sh语法里是无法解释的。

用户可以用chsh来改变,但是这个时候很容易出问题。

我个人觉得好的一个解决方案是,默认用sh->bash,在用到其他的时候在脚本第一行,指定所需要的解释器。
回复 支持 反对

使用道具 举报

发表于 2010-1-7 01:21:32 | 显示全部楼层
最基本的bash也不是很打才600K不到,压缩后。现在的机器,如果不是有特殊的需要。bash还是最加的选择。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表