子shell
http://bbs.csdn.net/topics/392292455
https://www.cnblogs.com/daniaoge/p/6161821.html
http://blog.csdn.net/qq_20327293/article/details/50425737
1.
如果需要使用父Shell来执行此脚本,可以使用:
命令行:. ./test.sh
注意.与./之间有一个空格符
子Shell继续开启子Shell
与父Shell启动子Shell方式一样,继续调用下去,即子Shell开启子Shell。
通过$SHLVL变量,可以知道当前所在Shell的层次
2.
linux 对 反斜线 ··会fork 出一个子进程。 unix 则不会 fork 子进程。
在一对括号 (...) 里可以放置一组指令,这些指令是在一个子 shell 里执行的。在子 shell 里的变量不能被这段子 shell 外的代码直接访问,也就是说子 shell 里的变量不能被父 shell 所存取,实际上它们是局部变量。
这里可以参考:(( ))和 [[ ]] 和 shell 与 命令的执行 这两篇文章。
############sampe 1:
父Shell与子Shell
Login Shell
登录主机后,在执行Bash Script之前,其实我们已经处于一个BashShell中。
这个Shell叫login Shell,是将来我们执行任何Script的上层环境。又叫父SHell
其实每个帐号都可以自定义loginShell。以Linux来说,帐号的login Shell定义在/etc/passwd这个文件中。
/etc/passwd的每一行代表一个帐号,共有7个字段,之间用:隔开。
帐号:x:UID 使用者代码:GID 群组代码:用户信息:主目录:login shell路径
第二栏x为密码栏,基于系统安全考虑,编码后的密码已经被放入/etc/passwd文件中。
login Shell定义在第7个字段,如果这个字段的Shell程序不存在、不合法,或执行失败,则无法登录主机。
父Shell、子Shell
当在执行一个Shell Script时,父Shell会根据Script程序的第一行#!之后指定的Shell程序开启一个子Shell环境,然后在子Shell中执行此Shell Script。一旦子Shell中的Script执行完毕,此子Shell随即结束,回到父Shell中,不会影响父Shell原本的环境。
子Shell环境拥有与父Shell相同的环境变量、标准输入、输出、错误等。
例如:
test.sh文件内容
#!/bin/bash
cd /var/www/html
命令行:chmod +x /test.sh
命令行:./test.sh
执行完脚本后还原到父Shell,并且父Shell并没有进入/var/www/html目录。
注:这是因为当执行Shell文件时,父Shell会创建子Shell,各自独立。
如果需要使用父Shell来执行此脚本,可以使用:
命令行:. ./test.sh
注意.与./之间有一个空格符
子Shell继续开启子Shell
与父Shell启动子Shell方式一样,继续调用下去,即子Shell开启子Shell。
通过$SHLVL变量,可以知道当前所在Shell的层次
#############sampe 2
linux 对 反斜线 ··会fork 出一个子进程。 unix 则不会 fork 子进程。
在一对括号 (...) 里可以放置一组指令,这些指令是在一个子 shell 里执行的。在子 shell 里的变量不能被这段子 shell 外的代码直接访问,也就是说子 shell 里的变量不能被父 shell 所存取,实际上它们是局部变量。
这里可以参考:(( ))和 [[ ]] 和 shell 与 命令的执行 这两篇文章。
下面用一段代码进行测试:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#!/bin/bashechoouter_variable=Outerouter_variable2=Outer2( echo inner_variable=Inner outer_variable2=Outer_var_changein_subshell echo echo echo)echoechoechoechoechoif"$inner_variable"then echoelse echofiexit |
运行输出:
引用beyes@debian:~/shell$ ./subshell.sh
Subshell level = 0
Subshell level INSIDE subshell = 1
From Subshell,"inner_variable"=Inner
From parent shell,"outer"=Outer
From parent shell, "outer"=Outer_var_changein_subshell
In parent shell, check "outer_variable" value:Outer
In parent shell, check "outer_variable2" value:Outer2Subshell level OUTSIDE subshell = 0
inner_variable undefined in main body of shell
在上面的代码中,BASH_SUBSHELL 是一个环境变量,它表示进入子 shell 的层级,比如处于当前 shell 时,该变量值为 0;当在当前 shell 派生的子 shell 里时,该变量值为 1;如果该子 shell 又派生出一个子 shell,那么该变量在此间的值就为 3,以此类推。
在代码中,( ) 里的代码段是在子 shell 里执行的,而 inner_variable 作为局部变量,它的值可以在 ( ) 这段代码里 echo 出来,但是一旦返回到父shell 时,它就是未定义的,所以会输出“ inner_variable undefined in main body of shell”。也就是说,局部变量不能被外部代码所访问。
从输出可以看到,在子 shell 中和父 shell 中变量 outer_variable 的输出值是一样的;相对应的 outer_variable2 变量即使在子 shell 中进行了修改,但是当返回到父 shell 对其输出时,它却还是父 shell 中原来所赋的值。从这里可以看出,子 shell 可以 “感知” 父 shell 中的变量,但它不能修改它。其本质的原因和 fork() 函数的原理有关。在 UNIX/LINUX 中,fork 出来的子进程实际上是对父进程的一种拷贝,而子 shell 就是父shell fork 出来的一个子进程,所以它理所当然的有了父shell 中的一片拷贝。所以,子 shell 里的 outer_variable 和 outer_variable2 变量虽然和父 shell 的同名,但它们并不是同一个变量,而是父 shell 里的一个副本。
说到父shell 和 子 shell,那么会想到 export 这个命令。export 也是 bash 的一个内置命令。它主要是用来将父 shell 里的变量导出供子 shell 使用。它有如下特征:
1. 用 export 导出的变量放在“导出变量列表”中,它可以被子 shell (子 shell 的子 shell 也是如此)拷贝并使用。
2. 被 export 出来的变量虽然可以被子 shell 使用,但它也只是一个拷贝,而不会影响到父 shell 中的值以及其它子 shell 中的值。
看下面示例;
1. 先在当前 shell 里 export 一个变量:
引用beyes@debian:~/shell$ export exp8temp="hello world"
beyes@debian:~/shell$ echo $exp8temp
hello world
2. 运行一个脚本 echo 此变量(该脚本只有一句话即 echo $exp8temp ):
引用$ ./exp8.sh
hello world
由上可见,父 shell 里 export 的变量可以被子 shell 读取。
3. 测试一下子 shell 更改此变量是否会影响父 shell 里的值,子 shell 代码如下:
|
1
2
3
4
5
|
#!/bin/bashexp8temp="helloecho |
检验上面的情景:
引用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 是否能读到呢?
先将下面一段代码放在后台运行:
|
1
2
3
4
5
6
7
|
#!/bin/bashexport"hellosleepexit |
然后在在 30 秒内在父 shell 里读取一下 $exp9temp 的值,发现输出为空。所以我们得出结论,export 出来的变量不能导出到父进程或者是父进程的环境里。一个自己称可以继承父进程的东西,而不能反过来去影响父进程。
那么子 shell 有什么办法可以向父 shell 传递自己的变量吗?下面方法可以考虑:
1. 通过一个中间文件进行:
|
1
2
3
4
5
6
7
8
9
10
|
#!/bin/bash( subvar="hello echo )readecho |
运行输出:
引用$ sh subandp.sh
hello shell
2. 通过命令替换:
引用#!/bin/bashpvar=`subvar="hello shell";echo $subvar`
echo $pvar
运行输出:
引用$ ./subandp.sh
hello shell
执行命令替换符(两个反单引号)之间的命令也是在子 shell 来完成的。
3. 使用命名管道:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#!/bin/bashmkfifo( subsend="hello echo )readechoexit |
运行输出:
引用beyes@debian:~/shell$ ./var.sh
hello world
关于有名管道创建命令 mkfifo 可参考:http://www.groad.net/bbs/read.php?tid-3707.html
4. 使用 here 文档:
|
1
2
3
4
5
6
7
8
|
#!/bin/bashread`subvar="helloechoHEREecho |
运行输出:
引用$ ./subandp.sh
hello shell
方法应该还有很多,这些方法的本质原理基于进程间的通信。
子shell的更多相关文章
- 统计文件种类数+获取子shell返回值的其它方法
前言 只是作为一个shell的小小练习和日常统计用,瞎折腾的过程中也是摸到了获取子shell返回值的几种方法: 肯定还有别的方法,跟进程间的通信相关,希望你能提出建议和补充,谢谢~ 完整程序: #! ...
- 命令行子shell 括号 ()
子shell 控制变量 ansible-direc:~ # (export hello=world;echo $hello)worldansible-direc:~ # echo $hello ans ...
- Linux Shell编程(27)——子shell
运行一个shell脚本时会启动另一个命令解释器. 就好像你的命令是在命令行提示下被解释的一样, 类似于批处理文件里的一系列命令.每个shell脚本有效地运行在父shell(parent shell)的 ...
- 进入子shell的各种情况分析
子shell的概念贯穿整个shell,写shell脚本时更是不可不知.所谓子shell,即从当前shell环境新开一个shell环境,这个新开的shell环境就称为子shell(subshell),而 ...
- Linux编程 9 (shell类型,shell父子关系,子shell用法)
一. shell类型 1.1 交互式 bin/ shell程序 当用户登录到某个虚拟控制台终端或是在GUI中启动终端仿真器时,默认的shell程序就会开始运行.系统启动什么样的shell程序取决于你 ...
- Linux中shell和子shell一点点理解
Linux执行脚本有两种方式,主要区别在于是否建立子shell 1.像sh,bash,./命令是用来执行shell脚本的,在bash/sh命令下,脚本文件可以无"执行权限",即 ...
- 子shell以及什么时候进入子shell
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 子shell的概念贯穿整个shell,写shell脚本时更是不 ...
- 批量kill java进程方法-引出子shell和反引用
方法: kill –9 `pgrep java` 使用上述命令可以将服务器上运行的所有java进程一次性kill掉. 扩展:子shell和反应用在shell脚本中的作用 先来看一个子shell的例子: ...
- linux 子shell subshell和函数
关于子shell, subshell 参考:http://blog.csdn.net/sosodream/article/details/5683515 系统引导时的进程为 "原始进程&qu ...
- centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数据库读写分离 双主搭建 mysql.history 第二十九节课
centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数 ...
随机推荐
- 【转载】Android进程保活招式大全
原文地址:http://dev.qq.com/topic/57ac4a0ea374c75371c08ce8 目前市面上的应用,貌似除了微信和手Q都会比较担心被用户或者系统(厂商)杀死问题.本文对 An ...
- 谈谈javaScript
谈谈javaScript (杰我学习) 一. 什么是JavaScript 人们通常所说的JavaScript,其正式名称为ECMAScript.这个标准由ECMA组织发展和维护.ECMA ...
- AutoIT:界面与自动化操作结合来简化日常劳动: .Net Reactor验证License,设置License,创建License,截图AutoIt自动化实现。(七)
版本六中存在一个显著问题是: 当exe文件生存之后,运行的时候,通过consoleWrite函数打印出来的数据是无法展示出来的.这就存在一个问题:当运行失败的时候,我还是看不到任何log信息. 于是, ...
- C# 使用WebClient时,在多网卡时,指定IP发送Web请求
需要定义一个类,重写GetWebRequest,在方法内,指定IP地址 public class MyWebClient : WebClient { private IPAddress ipAddre ...
- python--numpy模块、spicy模块、 matplotlib模块
一:numpy模块 ndarray:存储单一数据类型的多维数组 ufunc:能够对数组进行处理的函数(universal function object) #numpy 中arange用法,指定开始值 ...
- monkeyRunner
MonkeyRunner工具是使用Jython(使用Java编程语言实现的Python)写出来的,它提供了多个API,通过monkeyrunner API 可以写一个Python的程序来模拟操作控制A ...
- UVa 1660 Cable TV Network (最大流,最小割)
题意:求一个无向图的点连通度. 析:把每个点拆成两个,然后中间连接一个容量为1的边,然后固定一个源点,枚举每个汇点,最小割. 代码如下: #pragma comment(linker, "/ ...
- 【转】Visual Studio 选择相同变量高亮
转:http://www.cnblogs.com/stone_w/p/3613760.html 前段时间一直在使用matlab,今天需要使用vs2008,而用惯了matlab,习惯了其中一项选中变量高 ...
- 不能支持C++11的特性~,升级到4.8.2
一.简易安装 操作环境 CentOS6.5 64bit,原版本4.4.7,不能支持C++11的特性~,希望升级到4.8.2 不能通过yum的方法升级,需要自己手动下载安装包并编译 1.1 获取安装包并 ...
- Angular6之ng build | ng build --aot | ng build --prod 差异
由于写了大半年的项目终于要告一段落并且即将进行第二阶段优化开发,emmm 基础版本已经二十多个模块了,必不可少的优化是很重要的,尽管项目上使用多层嵌套懒加载,但是在首屏加载的时候,任然很慢啊,因为一直 ...