013-在 Shell 脚本中调用另一个 Shell 脚本的三种方式

如下:

  • fork: 如果脚本有执行权限的话,path/to/foo.sh。如果没有,sh path/to/foo.sh
  • exec: exec path/to/foo.sh
  • source: source path/to/foo.sh

1、fork

fork 是最普通的, 就是直接在脚本里面用 path/to/foo.sh 来调用
foo.sh 这个脚本,比如如果是 foo.sh 在当前目录下,就是 ./foo.sh。运行的时候 terminal 会新开一个子 Shell 执行脚本 foo.sh,子 Shell 执行的时候, 父 Shell 还在。子 Shell 执行完毕后返回父 Shell。 子 Shell 从父 Shell 继承环境变量,但是子 Shell 中的环境变量不会带回父 Shell。

2、exec

exec 与 fork 不同,不需要新开一个子 Shell 来执行被调用的脚本. 被调用的脚本与父脚本在同一个 Shell 内执行。但是使用 exec 调用一个新脚本以后, 父脚本中 exec 行之后的内容就不会再执行了。这是 exec 和 source 的区别.

3、source

与 fork 的区别是不新开一个子 Shell 来执行被调用的脚本,而是在同一个 Shell 中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用。

测试

脚本1、父脚本

#!/usr/bin/env bash

A=1

echo "执行调用之前进程Id exec/source/fork: PID for 1.sh = $$"

export A
echo "In 1.sh: variable A=$A"

case $1 in
        --exec)
                echo -e "==> using exec…\n"
                exec ./2.sh ;;
        --source)
                echo -e "==> using source…\n"
                . ./2.sh ;;
        *)
                echo -e "==> using fork by default…\n"
                ./2.sh ;;
esac

echo "执行调用之后进程Id exec/source/fork: PID for 1.sh = $$"
echo -e "父脚本1.sh: variable A=$A\n"

脚本2、子脚本

#!/usr/bin/env bash

echo "子脚本2PID for 2.sh = $$"
echo "In 2.sh get variable A=$A from 1.sh"

A=2
export A

echo -e "子脚本2.sh默认A=2: variable A=$A\n"

测试一、fork方式,直接调用

$ ./1.sh
执行调用之前进程Id exec/source/fork: PID for 1.sh = 71145
In 1.sh: variable A=1
==> using fork by default…

子脚本2PID for 2.sh = 71146
In 2.sh get variable A=1 from 1.sh
子脚本2.sh默认A=2: variable A=2

执行调用之后进程Id exec/source/fork: PID for 1.sh = 71145
In 1.sh: variable A=1

fork 方式可以看出,两个脚本都执行了,运行顺序为1-2-1,从两者的PID值(1.sh PID=71145, 2.sh PID=71146),可以看出,两个脚本是分成两个进程运行的。

扫描二维码关注公众号,回复: 7958560 查看本文章

测试二、exec方式:./1.sh exec

$ ./1.sh exec
执行调用之前进程Id exec/source/fork: PID for 1.sh = 71288
In 1.sh: variable A=1
==> using exec…

子脚本2PID for 2.sh = 71288
In 2.sh get variable A=1 from 1.sh
子脚本2.sh默认A=2: variable A=2

exec 方式运行的结果是,2.sh 执行完成后,不再回到 1.sh。运行顺序为 1-2。从pid值看,两者是在同一进程 PID=71288 中运行的。

测试三、source方式:./1.sh source

$ ./1.sh source
执行调用之前进程Id exec/source/fork: PID for 1.sh = 71319
In 1.sh: variable A=1
==> using source…

子脚本2PID for 2.sh = 71319
In 2.sh get variable A=1 from 1.sh
子脚本2.sh默认A=2: variable A=2

执行调用之后进程Id exec/source/fork: PID for 1.sh = 71319
父脚本1.sh: variable A=2

source方式的结果是两者在同一进程里运行。该方式相当于把两个脚本先合并再运行。

对比

Command 进程 变量 Explanation
fork 父子不同进程 子继承父变量,子不能传递给父 新开一个子 Shell 执行,子 Shell 可以从父 Shell 继承环境变量,但是子 Shell 中的环境变量不会带回给父 Shell。
exec 同进程 子继承父,子进程结束 在同一个 Shell 内执行,但是父脚本中 exec 行之后的内容就不会再执行了,相当于父脚本执行exec进入子脚本后不再回到父脚本。
source 同进程 子继承父变量,子同时回传给父 在同一个 Shell 中执行,在被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用,相当于合并两个脚本在执行。

 脚本地址:https://github.com/bjlhx15/shell.git 下的test/invokesh

 

猜你喜欢

转载自www.cnblogs.com/bjlhx/p/11921311.html