目录

一、问题提出

二、使用sh和./执行脚本文件的区别

1、解释器指定:

2、依赖性

3、环境变量

4、脚本特性

5、性能

三、问题分析和解决

1、问题分析

2、问题解决

四、举例

1、脚本代码

2、脚本执行

(1)./方式执行

(2)sh方式执行

(3)分析

3、兼容性考虑

五、总结


一、问题提出

       运行bash脚本的时候,我们最常用的是./ 和 sh 方式,平常运行的话都是正常。但是,有时候可能会发现使用sh执行的时候会出现一些错误。

        如下图所示,同样一个脚本文件,没有任何改变,发现使用sh来执行的时候,出现语法错误。但是使用./来执行的时候,发现没有任何错误,能够输出正确的结果。为什么呢?

        下面让我们来看一看使用这两种方式有哪些地方不一样?来探究其中的区别和联系。

二、使用sh和./执行脚本文件的区别

        使用 ./ 和 sh 运行 Bash 脚本在行为上会有一些区别,具体取决于脚本的内容、权限以及系统的配置。以下是两者的一些主要区别:

1、解释器指定:

        ./scriptname.sh: 这种方式假设脚本文件的第一行以 #!/bin/bash 或其他解释器路径开头(称为 shebang),它会告诉系统使用哪个解释器来运行脚本。如果脚本没有指定 shebang,那么它将使用当前 shell 来执行。

        sh scriptname.sh: 这种方式明确告诉系统使用 sh(通常是 Bash 的一个链接或者兼容的 shell,如 dash 在某些 Linux 发行版中)来运行脚本,即使脚本中有一个不同的 shebang 行。

2、依赖性

        使用 ./scriptname.sh 要求脚本具有执行权限(通过 chmod +x scriptname.sh 设置),并且脚本文件的第一行需要正确指定解释器。

        使用 sh scriptname.sh 不要求脚本具有执行权限,因为它直接将脚本作为 sh 的参数传递。

3、环境变量

        当使用 ./scriptname.sh 时,脚本通常会在当前 shell 的环境中运行,这意味着它能够访问当前 shell 的所有环境变量。

        使用 sh scriptname.sh 可能会在一个子 shell 中运行脚本,这可能会影响环境变量的继承。

4、脚本特性

        如果脚本使用了 Bash 特定的特性,那么使用 sh scriptname.sh 可能会导致脚本无法正常运行,因为 sh 可能不支持这些特性。

        而使用 ./scriptname.sh(假设脚本指定了正确的 shebang 为 Bash)则不会有这个问题。

5、性能

        使用 ./scriptname.sh 通常会启动一个新的进程来运行脚本,而 sh scriptname.sh 也类似,但是在某些情况下,直接执行脚本可能比通过 sh 来执行要稍微快一些,因为它避免了额外的解释器调用。

三、问题分析和解决

1、问题分析

       文章前面的出现的问题,应该就是上面提到的脚本特性的问题。也就是sh 可能不支持代码中的一些特性。

        具体来讲,出现 “Syntax error: Bad for loop variable” 错误,是因为 sh 默认并不支持 C 风格的 for 循环语法。也就是说,sh(即 Bourne Shell)期望 for 循环使用不同的语法,而 C 风格的 for 循环是 Bash(Bourne Again Shell)特有的功能。

2、问题解决

       知道了问题的原因,我们可以改成符合sh的for循环的语法,具体如下:

for i in $(seq $START $END); do
    # 循环体
done

        实际操作如下:

四、举例

1、脚本代码

        以下是一个使用 Bash 特定特性的脚本示例,一个名为 `test_bash_feature.sh` 的脚本,内容如下:

#!/bin/bash
# 使用 Bash 的关联数组特性
declare -A animals
animals=([dog]="bark" [cat]="meow" [bird]="tweet")
# 循环遍历关联数组
for animal in "${!animals[@]}"; do
  echo "${animal} says ${animals[$animal]}"
done

        这个脚本使用了 Bash 的关联数组特性,这在传统的 `sh` shell 中是不支持的。

2、脚本执行

(1)./方式执行

        如果你尝试使用 `./test_bash_feature.sh` 运行这个脚本(假设它有执行权限并且正确设置了 shebang),它将正常工作并输出:

dog says bark

cat says meow

bird says tweet

(2)sh方式执行

        如果尝试使用 `sh test_bash_feature.sh` 运行同一个脚本,可能会遇到错误,因为 `sh` 不支持关联数组。错误输出可能如下:

test_bash_feature.sh: 4: declare: not found

test_bash_feature.sh: 5: Syntax error: "(" unexpected

        实际操作如下:

(3)分析

        这个错误是因为 `sh` 不理解 `-A` 选项(用于声明关联数组)和关联数组的语法。因此,脚本在尝试声明和使用关联数组时失败了。

3、兼容性考虑

        为了确保脚本能够在不支持 Bash 特性的环境中运行,需要避免使用这些特性,或者检查脚本运行的 shell 类型,并在必要时提供替代的代码路径。例如,可以使用以下方式来检查是否在 Bash 中运行:

if [ -n "$BASH_VERSION" ]; then
  # Bash-specific code here
else
  # Fallback code for a more generic shell
Fi 

        这样,可以为不同的 shell 提供不同的实现,从而确保脚本的兼容性。

五、总结

        通过以上的分析和举例,我们可以看出,如果想要确保脚本使用特定的 shell(如 Bash)来运行,并且脚本具有执行权限,那么使用 ./scriptname.sh 是更好的选择。

        如果想要确保脚本在任何情况下都使用 sh 来运行,或者脚本没有执行权限,那么使用 sh scriptname.sh 可能更合适。


文章正下方可以看到我的联系方式:鼠标“点击” 下面的 “威迪斯特-就是video system 微信名片”字样,就会出现我的二维码,欢迎沟通探讨。


Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐