相同的 shell 脚本在不同的 Linux 发行版上具有不同的行为

Posted

技术标签:

【中文标题】相同的 shell 脚本在不同的 Linux 发行版上具有不同的行为【英文标题】:Same shell script has different behaviour on different Linux distributions 【发布时间】:2013-08-07 02:12:30 【问题描述】:

我只是简单地编写了一个 shell 脚本来让我轻松地编译我的代码。我的目录树如下所示:

TOPDIR
|
+--- DIR[1]
.
.
.
+--- DIR[n]
|
+--- DIR[n+1]
      |
      +--- makefile

我曾经使用以下命令来编译我的代码:

$cd DIR[n+1]
$make

因为我想在编译完代码后回到 TOPDIR,所以我输入:

$cd -

我想把它放在一个 shell 脚本文件中,所以我写:

#! /bin/sh
cd $HOME/$WORKDIR/$MAKEDIR
make
cd -

效果很好,在此之后,我从我们的供应商那里获得了新代码,它改变了制作过程中的一些东西。目录树看起来和以前几乎一样,但它使用一个 shell 脚本来启动 make 过程:

TOPDIR
|
+--- DIR[1]
|
+--- DIR[2]
.
.
.
+--- DIR[N]
      |
      +--- DIR[n]
      |     |
      |     +---build_1.sh
      +---build_2.sh

在 build_1.sh 中,它只包含:

#! /bin/sh
source ../build_2.sh

因此,我首先使用:

$cd DIR[n]
$./build_1.sh

编译后,我使用:

$cd -

但我在脚本中编写命令:

#! /bin/sh
cd DIR[n]
./build_1.sh
cd -

它告诉我:

./build_1.sh: 2: ./build_1.sh: source: not found

我在openSUSE 上使用相同的脚本;它没有问题。但是在ubuntu-13.04 上,它会弹出错误消息。我在ubuntu-13.04中测试了source函数,使用没问题。

对此问题有何评论?

【问题讨论】:

这里广泛猜测:在 ubuntu 中,/bin/sh 链接到 /bin/dash。将shebang更改为/bin/bash,看看问题是否消失。 @Paulo Scardine,非常感谢!!它有效,我能知道bashdash之间的区别 我已经做了完整的回答,希望以后能帮助到其他人。 我建议在脚本中使用 cd - 是次优的。您应该使用子外壳来避免需要执行cd -。如果你做(cd dir[N+1]; make),子shell在子目录下运行,但父shell根本没有改变目录。 【参考方案1】:

在 Ubuntu 中,默认的 shell /bin/sh 是到 /bin/dash - bashdash 的符号链接,它们有足够多的共同功能,大多数人从未意识到它们的区别,但它们并不相同(破折号的意思是更轻)。

Debian Almquist shell (dash) 是一个 Unix shell,比 Bash 小得多,但它仍然致力于 POSIX 兼容。它需要较少的磁盘空间,但功能也较少。 - ***

在坚持使用 POSIX 语法时您应该是安全的,但如果您的脚本正在使用仅在 bash 中可用的功能,请务必将 shebang 从 /bin/sh 更改为 /bin/bash 以避免出现 @ 987654328@ 不是bash

所以我的建议是:永远不要假设 bash 是默认 shell,如果可以的话,坚持使用 POSIX 标准的语法,或者在 shebang 处明确指向 /bin/bash

【讨论】:

以上是关于相同的 shell 脚本在不同的 Linux 发行版上具有不同的行为的主要内容,如果未能解决你的问题,请参考以下文章

Linux通用KVM自动安装Shell脚本(兼容所有Linux发行版/CentOS/Ubuntu)

《Linux命令行与shell脚本编程大全 第3版》

《Linux命令行与shell脚本编程大全》23章24章

相同的 git 版本,相同的 Linux 发行版,不同的 git 分页设置

shell脚本

Bash编程013——环境变量