脚本中调用脚本,有三种方式

1.fork
2.exec
3.source

需要用到的示例

a.sh

#!/bin/bash

if [ -n "$2" ];then
 do_date=$2
else
 do_date=`date -d "-1 day" +%F`
fi
 echo "=======a.sh时间:$do_date======="

 echo "a.sh===Pid:$$"
# export do_date
case $1 in
    --sh)
		sh b.sh $do_date
		sh c.sh $do_date;;
    --exec)
		exec ./b.sh $do_date
		exec ./c.sh $do_date;;
    --source)
		source b.sh $do_date
		source c.sh $do_date;;
esac
echo "====a.sh执行完成========"

b.sh

#!/bin/bash

if [[ -n "$1" ]];then
 do_date=$1
else
 do_date=`date -d "-1 day" +%F`
fi
echo "=======b.sh时间:$do_date======="

echo "b.sh===pid: $$"

c.sh

#!/bin/bash

if [ -n "$1" ];then
 do_date=$1
else
 do_date=`date -d "-1 day" +%F`
fi
echo "=======c.sh时间:$do_date======="

echo  "c.sh===Pid:$$"

fork

fork是最普通的一种调用方式,如果有执行权限,可以直接调用,如:要执行的脚本是 a.sh 在当前目录直接执行即可: ./a.sh,
如果没有执行权限,那么需要加上sh 或者 bash 。即:sh ./a.sh(ubuntu系统sh 默认调用dash,dash和bash是有区别的,最后说一下遇到的坑)。这种方式在调用时,会新起一个进程。所以它的执行流程会按照顺序依次执行。

执行流程:a.sh–>b.sh–>c.sh–> a.sh执行完成

结果:

脚本调用wireshark 脚本调用脚本shell_bash

可以看出a.sh 会启用一个进程,b.sh c.sh 分别会启用新的进程。

exec

在脚本中使用exec 调用另一个脚本,不会重新启动一个进程来执行,意味着 a.sh 和 b.sh 是同一个进程,但是exec执行完b.sh之后,进程就会结束。a.sh之后的代码不会在执行。

执行流程:
a.sh–>b.sh

结果:

脚本调用wireshark 脚本调用脚本shell_bash_02

source

在脚本中使用source调用另一个脚本,和exec相同,都是在同一个进程,但是source和exec的区别是source会执行完所有代码

执行流程:a.sh–>b.sh–>c.sh–>a.sh执行完成

结果:

脚本调用wireshark 脚本调用脚本shell_执行流程_03

问题

下面说一个sh 执行遇到的问题

当使用sh执行的时候,细心的同学已经发现了,b.sh中的打印的时间和其他的时间不同。而且执行还报错了:b.sh: 3: [[: not found。

我当时在项目中用到了脚本中调用脚本,用的就是第一种方法,而且是 sh执行的。我当时的需求是要把参数传到调用的脚本中,选择了第一种方法。但是为什么传进去参数会报错呢,然后我开始找原因。看了关于报错提示的文章 为什么[[ 会找不到?因为我用的是ubuntu系统,而ubuntu系统sh 默认用的是dash 。下图可以看到 sh 通过软连接 指向了dash

脚本调用wireshark 脚本调用脚本shell_开发语言_04


而 dash 和 bash 是有区别的:

bash: 支持[[ ]], 可实现正则匹配等强大功能

dash: 不支持[[ ]], 替代方法,采用外部命令

所以当我换成bash ok 问题成功解决。当然,也可以把b.sh中使用的 [[ ]] 换成 [ ] 也可以解决我这里的问题