ubuntu上的sh链接到dash

本文详细介绍了Ubuntu系统中dash和bash的区别。dash是POSIX合规的Shell,小巧快速,主要用于脚本执行,而bash是常用的GNU Bourne-Again Shell,功能更丰富。文章列举了多个bash特有的特性在dash中不被支持的例子,如函数定义、select语句、here string、进程替换等,并提供了相应的兼容性解决方案。
摘要由CSDN通过智能技术生成
最近同事写的shell脚本在ubuntu上跑时总走不对if的分支。发现ubuntu上的shell默认是bash,但sh对应的是dash,这个需要注意。


1
ubuntu上sh连到dash:
zxw@hostname1:~$ uname -a
Linux hostname1 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
zxw@hostname1:~$ cat /etc/issue
Ubuntu 12.04.4 LTS \n \l

zxw@hostname1:~$ echo $SHELL
/bin/bash
zxw@hostname1:~$ type sh
sh is hashed (/bin/sh)
zxw@hostname1:~$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash
zxw@hostname1:~$ 


centos上sh连到bash:
[root@hostalonetest ~]# uname -a
Linux hostalonetest 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
[root@hostalonetest ~]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m

[root@hostalonetest ~]# echo $SHELL
/bin/bash
[root@hostalonetest ~]# type sh
sh is /bin/sh
[root@hostalonetest ~]# ls -l /bin/sh
lrwxrwxrwx. 1 root root 4 Sep  1 07:45 /bin/sh -> bash
[root@hostalonetest ~]# echo $SHELL
/bin/bash
[root@hostalonetest ~]# 

2
写了个小脚本测试

zxw@hostname1:~$ nl test2.sh 
     1  #!/bin/bash
       
     2  tt='xx';
       
     3  if [ "$tt" == "YY" ]; then
     4    echo "yy"
     5  elif [ "$tt" == "xx" ]; then
     6    echo "xx"
     7  else
     8    echo "fuck"
     9  fi

3
在ubuntu上走sh用的是dash,测试脚本有错,同时走错了分支
zxw@hostname1:~$ sh test2.sh 
test2.sh: 5: [: xx: unexpected operator
test2.sh: 7: [: xx: unexpected operator
fuck

在ubuntu上走默认shell,用的是bash,结果ok
zxw@hostname1:~$ ./test2.sh 
xx

4
在centos上走sh用的是bash,结果ok
[root@hostalonetest ~]# sh test.sh 
yy
在centos上走默认shell,用的是bash,结果ok
[root@hostalonetest ~]# ./test.sh 
yy

5
可以用如下方法修改sh链到bash

ln -s /bin/bash /bin/sh
或者如下:
sudo dpkg-reconfigure dash
出现提示界面问是否要dash的时候,选No就行了。反馈如下:
  Removing 'diversion of /bin/sh to /bin/sh.distrib by dash'                     
  Adding 'diversion of /bin/sh to /bin/sh.distrib by bash'
  Removing 'diversion of /usr/share/man/man1/sh.1.gz to /usr/share/man/man1/sh.distrib.1.gz by dash'
  Adding 'diversion of /usr/share/man/man1/sh.1.gz to /usr/share/man/man1/sh.distrib.1.gz by bash'
看来第二种方法还是比第一种方法做的完善。


检验结果,已经指向bash:
zxw@hostname1:~$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Sep 15 11:28 /bin/sh -> bash

6

什么是bash ?
Bash(GNU Bourne-Again Shell)是许多Linux平台的内定Shell,事实上,还有许多传统UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等,Shell Script大致都类同,当您学会一种Shell以后,其它的Shell会很快就上手,大多数的时候,一个Shell Script通常可以在很多种Shell上使用
什么是dash ?

man结果摘抄部分:
dash is the standard command interpreter for the system.  The current version of dash is in the process of being changed to conform with the POSIX 1003.2 and 1003.2a specifications for the shell.

网上抄了段,不知道信息出处:

DASH is a POSIX-compliant implementation of /bin/sh that aims to be as small as possible. It does this without sacrificing speed where possible. In fact, it is significantly faster than bash (the GNU Bourne-Again SHell) for most tasks.
比bash小而快的东西


########################

下面是有些同学翻译或总结的,也放到这儿备查

Ubuntu dash与bash的区别

http://blog.csdn.net/hansel/article/details/9817129


https://wiki.ubuntu.com/DashAsBinSh

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_title.html

从Ubuntu 6.10开始,默认使用dash(theDebian Almquist Shell)而不是bash(the GNUBourne-Again Shell). 但Login Shell还是bash. 原因是dash更快、更高效,而且它符合POSIX规范。Ubuntu在启动的时候会运行很多shell脚本,使用dash可以加快启动速度。

 

  • 如果解决bash和dash兼容性导致的问题
    •  
    • 在需要bash的脚本的第一行写上"#!/bin/bash" 
    • 在Makefile中可以设置

SHELL = /bin/bash

  • 如果需要修改默认为bash,请运行下面命令并选择no。注意这将影响所有的系统脚本。如果有脚本需要dash的特有功能,将引起问题(这种情况比较少)。

sudodpkg-reconfigure dash

  • 在新写的shell脚本里避免使用bash的扩展特性(bashism)。
    •  
    • 使用devscripts包的checkbashisms      命令可以检查shell脚本里是否存在bashism. 
    • 安装autoconf-doc包运行info autoconf命令可以阅读"Portable      Shell" 部分的文档来了解POSIX Shell。 
    • 在"["命令(test)中避免使用-a, -o,应该使用多个"[]"命令并用"&&",      "||"连接。
                  例如:下面的shell语句

[\( "$foo" = "$bar" -a -f /bin/baz \) -o ! -x /bin/quux ]

应该替换为:

((["$foo" = "$bar" ] && [ -f /bin/baz ]) || [ ! -x/bin/quux ])

  • 不应该使用"[["命令,而应该使用"["命令
  • 使用$((…))而不是((…))做算术计算。
  • 不能使用$((n++)),     $((--n)) ,而应该是$((n=n+1)) 和$((n=n-1))
  • 不要使用{}进行字符扩展,例如/usr/lib/libfoo.{a,so};    
  • 避免使用$'…'扩展转义字符。例如,使用"$(printf     '\t')" 代替$'\t'
  • 不要使用$"…"进行字符串翻译。应该使用gettext.sh脚本。
  • 大部分的${…}进行变量扩展都是可移植的。但是下面的几个不是。
    •  
    • ${!...}进行非直接变量扩展,应该使用eval命令。 
    • ${parameter/pattern/string}进行模式替换 
    • ${parameter:offset:length}截取子串
  • 不要使用${parm/?/pat[/str]}进行字符替换,而应该使用echo, sed, grep,     awk等命令。例如:

OPENGL_VERSION=$(glxinfo| grep "OpenGL version string:")

OPENGL_VERSION=${OPENGL_VERSION/*:/}

 

应该使用:

OPENGL_VERSION=$(glxinfo| grep "OpenGL version string:" | awk 'BEGIN { FS =":[[:space:]]+" }; { print $2 }')

  • 不要使用${foo:3[:1]}进行子串切割,使用echo, sed, grep,     awk等命令。

例如:

string_after="somestring"

string=${string_after:0:3}

 

应该使用:

string=$(echo$string_after | awk  '{ string=substr($0,1, 3); print string; }' )

  • 在case语句中使用[!]而不是[^]。例如:

case"foo" in

    [^f]*)

        echo 'not f*'

    ;;

esac

 

替换为:

case"foo" in

    [!f]*)

        echo 'not f*'

    ;;

esac

  • dash 不支持$LINENO,虽然它是POSIX标准。
  • 不要使用$PIPESTATUS
  • 避免使用$RANDOM,而应读取/dev/urandom或者/dev/random。例如:

random=`hexdump-n 2 -e '/2 "%u"' /dev/urandom`

  • 一些echo的选项不是portable的,可能其他shell不支持。例如-e, -n
  • 函数名前不要加function关键字。
  • 不要使用let命令,直接使用=赋值。例如

let time=10 和 time=10一样

let time--和time=$((time-1))一样

  • bash和dash对local关键字的解释不一样。

local a=5 b=6;   //dash:a和b是全局变量,  bash则认为a和b是局部变量。

  • 不支持printf %q|%b
  • 不要使用select关键字,只有bash才支持。
  • source命令也是bash才支持,应该使用'.'命令
  • 路径搜索时,`dash` 不支持     `~` 扩展,应该使用$HOME
  • 不支持declare 或 typeset
  • bash和dash对ulimit和type有不同的选项
  • time是bash内置的命令,但是在dash下需要使用time程序
  • kill -[0-9] or     -[A-Z]是bash内置的命令
  • 在bash里,如果read没有接变量,则会保存在REPLY变量里。在dash应该使用read REPLY替代。
  • 不要使用<<<,而是使用<<替代。例如:

$cat <<<"$HOME is where the heart is."

/home/ralphis where the heart is.

 

替换为:

$cat <<E

>$HOME is where the heart is.

>E

/home/ralphis where the heart is.

$


#############################

Dash与Bash的语法区别
http://blog.163.com/hlz_2599/blog/static/142378474201182195320441/

如今Debian和Ubuntu中,/bin/sh默认已经指向dash,这是一个不同于bash的shell,它主要是为了执行脚本而出现,而不是交互,它速度更快,但功能相比bash要少很多,语法严格遵守POSIX标准,下面简要列举下从bash迁移到dash一般需要注意的问题

1.定义函数

bash: function在bash中为关键字

1
2
3
4
5
6
igi@gentoo ~ $ foo(){ echo  $0;}
igi@gentoo ~ $ foo
/bin/bash
igi@gentoo ~ $ function  foo2(){ echo  $0;}
igi@gentoo ~ $ foo2
/bin/bash

dash: dash中没有function这个关键字

1
2
3
4
5
$ foo(){ echo  $0;}
$ foo
dash
function  foo2(){ echo  $0;}
dash: Syntax error: "("  unexpected

2.select var in list; do command; done

bash:支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
igi@gentoo ~ $ select  input in  A B
do
>   case  $input in
>     A)
>        echo  'Input:A'
>        break
>        ;;
>     B)
>        echo  'Input:B'
>        break
>        ;;
>   esac
done
1) A <
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值