在同一个文件夹下有两个脚本。a.sh和b.sh,脚本内容例如以下:

a.sh:

echo "test for a"
source b.sh

b.sh:

echo "test for b"

使用bash a.sh 返回正确结果。

而使用sh a.sh返回结果例如以下:

test for a

a.sh: line 2: source: b.sh: file not found

明显脚本运行过程中。没有找到文件b.sh,将a.sh脚本内容改动为例如以下:

echo "test for a"
source ./b.sh

再次使用sh a.sh 又能够正常运行了,这是为什么呢?

问题就出在sh与bash运行脚本的差别。

  首先要明白重要的一点:/bin/sh 尽管是/bin/bash的软连接,但这个软连接非常特殊,它并不仅仅仅仅是一个链接,sh不等于bash。假设你在CentOS下使用man sh能够找到这句话:

Bash can be configured to be POSIX-conformant by default.

这说明sh 等于 bash -posix 也就是说使用sh来运行一个脚本,所以使用sh a.sh的效果等同于bash -posix a.sh,尽管大部分情况下等于使用bash来运行脚本,但启用了bash的posix模式,也能够理解为posix标准。

那么就要遵循这个标准下的要求。

如今来man bash在关于source命令的文档中找到这么一句话:

When bash is not in posix mode, the current directory is searched if no file is found in PATH.

假设bash不是运行在posix模式下,当文件名称最为source的參数系统假设在PATH中,也就是系统变量中找不到这个文件时会在当前文件夹下查找这个文件。

所以在不使用posix模式的情况下 a.sh脚本中的source b.sh不会出错,由于即使在PATH中找不到。也会在当前文件夹中进行查找。但假设使用了posix模式,能够在google中找到关于bash posix mode的内容。当中有一条:

The . and source builtins do not search the current directory for the filename argument if it is not found by searching PATH.

.也就是source这样的内建命令在使用文件名称作为參数时,假设在PATH中无法找到。将不会在当前文件夹自己主动进行查找。

这就是问题的关键。使用了sh 运行a.sh,脚本中source b.sh中的b.sh既不会在PATH中被找到也不会在当前文件夹下被找到,那么bash仅仅会返回

b.sh: file not found

但假设a.sh写成这样 source ./b.sh

这就不一样了,这等于给source提供了一个该文件的路径,尽管是相对路径,但bash是能够依据脚本本身运行的位置来找到b.sh的,所以就不会出错了。

总结:所以普通情况下。在Linux中运行一个bash的脚本。我们都会使用bash去运行。就是为了避免这样的奇怪问题的产生。

关于bash posix mode的相关信息你能够在这里找到:

http://structure.usc.edu/bash/bashref_6.html#SEC83

使用sh运行bash脚本的奇怪问题的更多相关文章

  1. Linux下运行bash脚本显示“: /usr/bin/env: "bash\r": 没有那个文件或目录

    用 ./ 运行bash脚本文件出现 报错信息 /usr/bin/env: "bash\r": 没有那个文件或目录 错误原因:这主要是因为bash后面多了\r这个字符的原因.在lin ...

  2. 实验楼-高级Bash脚本编程指南

    实验1.Bash介绍与入门 1.简介:Bash是一个为GNU计划编写的Unix shell,它是许多Linux平台默认使用的shell shell是一个命令解释器,是介于操作系统内核与用户之间的一个绝 ...

  3. source、sh、bash、./执行脚本的区别

    1.source命令用法: source FileName 作用:在当前bash环境下读取并执行FileName中的命令.该filename文件可以无"执行权限" 注:该命令通常用 ...

  4. linux 下source、sh、bash、./执行脚本的区别

    原文地址:http://blog.csdn.net/caesarzou/article/details/7310201 source命令用法: source FileName 作用:在当前bash环境 ...

  5. (转)source、sh、bash、./执行脚本的区别

    source.sh.bash../执行脚本的区别  原文:https://www.cnblogs.com/sparkbj/p/5976100.html 1.source命令用法: source Fil ...

  6. source sh运行脚本的差别

    主要有两种方式运行shell脚本 1)source test.bsh 2)sh test.bsh 1)souce运行脚本文件会在父程序中运行.各项动作都会在原本的bash内生效.运行过程不另开进程.脚 ...

  7. Bash脚本15分钟进阶指导

    首先声明这是网上摘来的.这里的技术技巧最初是来自谷歌的“Testing on the Toilet” (TOTT).这里是一个修订和扩增版本. 脚本安全 我的所有bash脚本都以下面几句为开场白: # ...

  8. 编写运行R脚本

    1.在后台运行R 1.1 创建file.R文件 1.2 在文件首行键入: #! /path/to/Rscript 1.3 在下面的行中,键入R代码 1.4 保存(记得有png(),jpeg(),... ...

  9. 【转】如何调试bash脚本

    本文转自:http://coolshell.cn/articles/1379.html Bash 是Linux操作系统的默认Shell脚本.Shell是用来处理操作系统和用户交互的一个程序.Shell ...

随机推荐

  1. 【【henuacm2016级暑期训练】动态规划专题 F】Physics Practical

    [链接] 我是链接,点我呀:) [题意] 给你n个数字 让你删掉最小的数字 使得: 剩余的数字中 "最大的数字"小于等于"最小的数字*2" [题解] 把数据从小 ...

  2. b.WHERE使用中多行子查询(适用于in,any,all条件)

    b.多行子查询(适用于in,any,all条件)   //查询与SCOTT和MARTIN在同一个部门的同事的编号和名称   select empno,ename   from emp   where ...

  3. IE6浏览器不支持固定定位(position:fixed)解决方案(转)

    IE6浏览器不支持固定定位(position:fixed)解决方案   来源:互联网 作者:佚名 时间:12-04 10:54:05 [大 中 小] 点评:有些朋友在进行网页布局时,会遇到IE6浏览器 ...

  4. SQL SERVER-安装和卸载

    卸载后无法正常安装SQL SERVER 删除了本机的SQL SERVER以后,我发现我本机的SQL SERVER 再也安装不上了,这个一个比较严重的问题,要每天定时备份数据库到指定的地方才能防止数据丢 ...

  5. 一个通用Makefile的编写

    作者:杨老师,华清远见嵌入式学院讲师. 我们在Linux环境下开发程序,少不了要自己编写Makefile,一个稍微大一些的工程下面都会包含很多.c的源文件.如果我们用gcc去一个一个编译每一个源文件的 ...

  6. iOS声明变量详解

    内容概述: 本文主要讲述了ios中多种声明变量方式的区别与联系,以及@interface声明的成员变量与@property属性的差异.最后介绍了推荐的声明方式. atany原创,转载请注明博主与博文链 ...

  7. CoreData 从入门到精通(三)关联表的创建

    上篇博客中讲了 CoreData 里增删改查的使用,学到这里已经可以应对简单的数据存储需求了.但是当数据模型复杂起来时,例如你的模型类中除了要存储 CoreData 里支持的数据类型外,还有一些自定义 ...

  8. 使用JS方法使页面滚动到指定元素+优化+API介绍(动画)

    前言 当页面最上部有顶部菜单是,使用锚点跳转的方法很容易挡住想要呈现的内容(如下图技能两个字被挡住了一半),为避免出现这样的问题,故滚动到指定元素使用用JS的方法来实现. 目录 使用的API简介 初版 ...

  9. Tomcat学习(一)——使用Eclipse绑定Tomcat并发布应用

    1.下载Tomcat 官网地址:http://tomcat.apache.org/whichversion.html 2.目录结构 bin:脚本目录 启动脚本:startup.bat 停止脚本:shu ...

  10. js中深拷贝代码实现

    function copy(original,o){ if(typeof original != 'object') return original; var o = o || (Array.isAr ...