父进程和子进程的变量传递

630阅读 0评论2015-10-22 sync_1521
分类:LINUX

一直以来我以为export会使一个变量变为环境变量,且全局生效。。

下面来把这个错误认识彻底纠正下。

export 也是 bash 的一个内置命令。它主要是用来将父 shell 里的变量导出供子 shell 使用。
它有如下特征:
1. 用 export 导出的变量放在“导出变量列表”中,它可以被子 shell (子 shell 的子 shell 也是如此)拷贝并使用。
2. 被 export 出来的变量虽然可以被子 shell 使用,但它也只是一个拷贝,而不会影响到父 shell 中的值以及其它子 shell 中的值。

1、执行脚本时是在一个子shell环境运行的,脚本执行完后该子shell自动退出;
2、一个shell中的系统环境变量才会被复制到子shell中(用export定义的变量);
3、一个shell中的系统环境变量只对该shell或者它的子shell有效,该shell结束时变量消失(并不能返回到父shell中)。
4、不用export定义的变量只对该shell有效,对子shell也是无效的。

执行一个脚本时,会先开启一个子shell环境(不知道执行其它程序是不是这样),然后将父shell中的所有系统环境变量复制过来,这个脚本中的语句就在子shell中执行。(也就是说父shell的环境变量在子shell中可以调用,但反过来就不行,如果在子shell中定义了环境变量,则只对该shell或者它的子shell有效,当该子shell结束时,也可以理解为脚本执行完时,变量消失。)为了证明这一点,请看脚本内容:
  test=’value’
  export test
这样的脚本执行完后,test实际上是不存在的。接着看下面的:
  test=’value’
  export test
  bash
这里在脚本最后一行再开一个子shell,该shell应该是脚本文件所在shell的子shell,这个脚本执行完后,是可以看到test这个变量的,因为现在是处于它的子shell中,当用exit退出子shell后,test变量消失。看下面示例;

先在当前 shell 里 export 一个变量:
beyes@debian:~/shell$ export exp8temp="hello world"
beyes@debian:~/shell$ echo $exp8temp
hello world
运行一个脚本 echo 此变量(该脚本只有一句话即 echo $exp8temp ):
$ ./exp8.sh
hello world
由上可见,父 shell 里 export 的变量可以被子 shell 读取。
测试一下子 shell 更改此变量是否会影响父 shell 里的值,子 shell 代码如下:
#!/bin/bash

exp8temp="hello shell"

echo $exp8temp
检验上面的情景:
beyes@debian:~/shell$ ./exp8.sh
hello shell
beyes@debian:~/shell$ echo $exp8temp
hello world
可见子 shell 对父 shell 里 export 出来的变量进行修改并不能影响到父 shell。
这说明了,子 shell 只是在“导出变量列表“里对该变量进行了一个拷贝。
但反过来,父shell再次更改此变量时,子 shell 再去读时,读到的是新值,而不是原来的值。

4. 如果在子 shell 里 export 出的变量,父 shell 是否能读到呢?先将下面一段代码放在后台运行:
#!/bin/bash

export exp9temp="hello world"

sleep 30

exit 0
然后在在 30 秒内在父 shell 里读取一下 $exp9temp 的值,发现输出为空。
所以我们得出结论,export 出来的变量不能导出到父进程或者是父进程的环境里。
一个自己称可以继承父进程的东西,而不能反过来去影响父进程。

那么子 shell 有什么办法可以向父 shell 传递自己的变量吗?下面方法可以考虑:
通过一个中间文件进行:
#!/bin/bash

(
 subvar="hello shell"
 echo "$subvar" > temp.txt
)

read pvar < temp.txt

echo $pvar

运行输出:
$ sh subandp.sh
hello shell
通过命令替换:
#!/bin/bash

pvar=`subvar="hello shell";echo $subvar`

echo $pvar
运行输出: ::
$ ./subandp.shhello shell
执行命令替换符(两个反单引号)之间的命令也是在子 shell 来完成的。
使用命名管道:
#!/bin/bash

mkfifo -m 777 npipe

(
  subsend="hello world"
  echo "$subsend" > npipe &
 )

read pread < npipe

echo "$pread"


exit 0
运行输出:
beyes@debian:~/shell$ ./var.sh
hello world
关于有名管道创建命令 mkfifo 可参考:
使用 here 文档:
#!/bin/bash


read pvar << HERE
`subvar="hello shell"
echo $subvar`
HERE

echo $pvar
运行输出:
$ ./subandp.sh
hello shell
方法应该还有很多,这些方法的本质原理基于进程间的通信。




上一篇:gsub使用变量
下一篇:screen命令