22 shell组命令与子进程
- 1.组命令
- 2.子进程
- 2.1 什么是子进程
- 2.2 创建子进程
- 2.3 子进程总结
- 3.如何检测子shell与子进程
1.组命令
组命令,就是将多个命令划分为一组,或者看成一个整体。
|
用法
|
区别
|
|---|---|
|
Shell 组命令的写法有两种: { command1; command2;. . .; } |
两种写法的重要不同:由 所以在子 Shell 环境中的任何更改都会消失(包括给变量赋值)。因此,在大多数情况下,除非脚本要求一个子 Shell, 否则使用 |
| 举栗 | |
| 将多条命令的输出重定向到out.txt文件 |
1.普通模式
2.使用组命令 { ls -l ;echo "test432";cat test.txt; }>out.txt (ls -l ;echo "test432";cat test.txt)>out.txt |
| 组命令与管道结合 |
(ls -l ;echo "test432";cat ../test.txt)|wc -l |
2.子进程
2.1 什么是子进程
子进程的概念是由父进程的概念引申而来的。在 Linux 系统中,系统运行的应用程序几乎都是从 init(pid为 1 的进程)进程派生而来的,所有这些应用程序都可以视为 init 进程的子进程,而 init 则为它们的父进程。
Shell 脚本是从上至下、从左至右依次执行的,即执行完一个命令之后再执行下一个。如果在 Shell 脚本中遇到子脚本(即脚本嵌套,但是必须以新进程的方式运行)或者外部命令,就会向系统内核申请创建一个新的进程,以便在该进程中执行子脚本或者外部命令,这个新的进程就是子进程。子进程执行完毕后才能回到父进程,才能继续执行父脚本中后续的命令及语句。
使用pstree -p命令就可以看到 init 及系统中其他进程的进程树信息(包括 pid):
systemd(1)─┬─ModemManager(796)─┬─{ModemManager}(821)
│ └─{ModemManager}(882)
├─NetworkManager(975)─┬─{NetworkManager}(1061)
│ └─{NetworkManager}(1077)
├─abrt-watch-log(774)
├─abrt-watch-log(776)
├─abrtd(773)
├─accounts-daemon(806)─┬─{accounts-daemon}(839)
│ └─{accounts-daemon}(883)
├─alsactl(768)
├─at-spi-bus-laun(1954)─┬─dbus-daemon(1958)───{dbus-daemon}(1960)
│ ├─{at-spi-bus-laun}(1955)
│ ├─{at-spi-bus-laun}(1957)
│ └─{at-spi-bus-laun}(1959)
├─at-spi2-registr(1962)───{at-spi2-registr}(1965)
├─atd(842)
├─auditd(739)─┬─audispd(753)─┬─sedispatch(757)
│ │ └─{audispd}(759)
│ └─{auditd}(752)
2.2 创建子进程
|
创建子进程的方式
|
说明
|
|
|---|---|---|
|
|
组命令、命令替换、管道 |
|
举栗: |
1.以新进程的方式运行脚本文件,比如 2.在当前 Shell 中使用 bash 命令启动新的 Shell |
2.3 子进程总结
子 Shell 虽然能使用父 Shell 的的一切,但是如果子 Shell 对数据做了修改,比如修改了全局变量,这种修改也只能停留在子 Shell,无法传递给父 Shell。不管是子进程还是子 Shell,都是“传子不传父”。
子 Shell 才是真正继承了父进程的一切,这才像“一个模子刻出来的”;普通子进程和父进程是完全不同的两个程序,只是维持着父子关系而已。
3.如何检测子shell与子进程
echo $$输出当前进程ID,echo $PPID输出父shell ID
|
命令 |
结果 |
结论 |
|
|---|---|---|---|
|
输出当前进程与父进程ID |
echo $$;echo $PPID |
34451 34450 |
|
|
子进程形式输出进程ID 子进程 |
bash echo $$;echo $PPID exit |
52886 34451 |
在普通的子进程中,$ 被展开为子进程的 ID |
|
组命令形式输出进程ID 子shell |
(echo $$;echo $PPID) |
34451 34450 |
子shell和父shell中的ID是一样的 这是因为$ 变量在子 Shell 中无效!Base 官方文档说,在普通的子进程中,$ 确实被展开为子进程的 ID; 但是在子 Shell 中,$ 却被展开成父进程的 ID |
|
管道形式输出进程ID 子shell |
echo "test" | { echo $$;echo $PPID; } |
34451 34450 |
|
|
进程替换形式输出进程ID |
read < <(echo $$ $PPID) $ echo $REPLY |
34451 34450 |
除了 $,Bash 还提供了另外两个环境变量——SHLVL 和 BASH_SUBSHELL,用它们来检测子 Shell 非常方便。
SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器,每次进入一层普通的子进程,SHLVL 的值就加 1。而 BASH_SUBSHELL 是记录一个 Bash 进程实例中多个子 Shell(sub shell)嵌套深度的累加器,每次进入一层子 Shell,BASH_SUBSHELL 的值就加 1。
| 命令 | 结果 | 知识点 | |
|---|---|---|---|
| 输出变量 |
echo "$SHLVL $BASH_SUBSHELL" |
1 0 |
|
|
子进程形式输出变量 子进程 |
创建一个脚本文件,命名为 test.sh,内容如下: #!/bin/bash echo "$SHLVL $BASH_SUBSHELL" ***************************************** bash echo "$SHLVL $BASH_SUBSHELL"#2 0 bash ./test.sh #3 0 echo "$SHLVL $BASH_SUBSHELL"#2 0 chmod +x ./test.sh;./test.sh #3 0 echo "$SHLVL $BASH_SUBSHELL"#2 0 exit #退出内层Shell echo "$SHLVL $BASH_SUBSHELL"#1 0 |
这两种运行脚本的方式,在脚本运行期间会开启一个子进程, 运行结束后立即退出子进程 产生新进程时,SHLVL的值加1 |
|
|
组命令形式输出变量 子shell |
(echo "$SHLVL $BASH_SUBSHELL") |
1 1 | 组命令、管道、命令替换这几种方式都会产生子 Shell |
|
管道形式输出变量 子shell |
echo "test" | { echo "$SHLVL $BASH_SUBSHELL"; } |
1 1 | |
|
命令替换形式输出变量 子shell |
var=$(echo "$SHLVL $BASH_SUBSHELL") echo $var |
1 1 | |
|
四层组命令形式输出变量 子shell |
( ( ( (echo "$SHLVL $BASH_SUBSHELL") ) ) ) |
1 4 | |
|
进程替换形式输出变量 |
read < <(echo "$SHLVL $BASH_SUBSHELL") echo $REPLY echo "hello" > >(echo "$SHLVL $BASH_SUBSHELL") |
1 0 1 0 |
进程替换只是借助文件在()内部和外部命令之间传递数据, 并没有创建子shell, (也就是当前进程)中执行的 |
22 shell组命令与子进程的更多相关文章
- dirname和shell常用命令
$ cd `dirname $0` 和PWD%} 显示当前目录名称${#var} 替换为变量字符个数特殊变量$ 当前SHELL的PID? 前一个命令的退出状态! 后台执行的上 ...
- 常用shell脚本命令
常用shell脚本命令 1.显示包含文字aaa的下一行的内容: sed -n '/aaa/{n;p;}' filename 2.删除当前行与下一行的内容: sed -i '/aaa/{N;d;}' f ...
- 4.Shell内部命令
4.Shell内部命令内部命令是由shell自身提供的.如果某个内部命令的名称是一个简单命令的第一个单词,shell会直接执行这个命令,而不会启动其它程序.对于一些不可能或者不方便通过外部程序实现的功 ...
- 运维 04 Shell基础命令(二)
Shell基础命令(二) 查看Linux的发行版 cat /etc/redhat-release cat /etc/os-release 查看系统用户的id信息 id 用户名 id root id ...
- shell 一些命令(转)
shell 一些命令(转) https://www.cnblogs.com/amei0/p/8041989.html 参考文档 http://man.linuxde.net/ 一.awk 求和 awk ...
- linux 基础 shell脚本命令
#########shell脚本命令#### 1.diff diff file file1 ####比较两个文件的不同 -c ####显示周围的行 -u ####按照一格式统一输出生成补丁 -r ## ...
- Linux Shell : Test命令参数解析
格式: test conditions test -n string : string 不为空 test -z string : string 为空 test int1 -eq int2 : int ...
- Linux shell 内部命令与外部命令有什么区别以及怎么辨别
内部命令实际上是shell程序的一部分,其中包含的是一些比较简单的linux系统命令,这些命令由shell程序识别并在shell程序内部完成运行,通常在linux系统加载运行时shell就被加载并驻留 ...
- mac os 添加用户到组 命令
mac os 添加用户到组 命令 dscl localhost 进入组目录 cd /Local/Default/Groups 使用ls 你就可以看到所有的group,? /Local/Default/ ...
随机推荐
- python文件处理(对比和筛选)
#!/user/bin/python #!coding=utf-8 # -*- coding: utf-8 -*- # 2017-9-25 #author:jingwenshuai import sy ...
- Nginx|Apache目录权限禁止执行PHP设置
Ngnix: location ~ /upload/.*.(php|php5)?$ { deny all; } 这就是禁止upload内执行php,但是图片可以打开哦 多目录禁止: location ...
- CRC校验原理简介及C代码实现说明
1 原理 参考文档:CRC校验 (qq.com) 参考书籍:<计算机网络(第7版)-谢希仁> 1.1 原理简介 CRC是一种检错方法. 在发送端,先把数据划分为组,假定每组k个比特.现假定 ...
- Tengine AIFramework框架
Tengine AIFramework框架 在开源大势下,以数据.算力.算法为三驾马车的人工智能实现了初级阶段的产业化落地.任何一个技术领域成熟的标志是从应用到平台的成功迭代,AI 也不例外,最终引导 ...
- 计图MPI分布式多卡
计图MPI分布式多卡 计图分布式基于MPI(Message Passing Interface),主要阐述使用计图MPI,进行多卡和分布式训练.目前计图分布式处于测试阶段. 计图MPI安装 计图依赖O ...
- CVPR2020:4D点云语义分割网络(SpSequenceNet)
CVPR2020:4D点云语义分割网络(SpSequenceNet) SpSequenceNet: Semantic Segmentation Network on 4D Point Clouds 论 ...
- mybatis学习——properties属性实现引用配置文件
Mybatis核心配置文件中有很多的配置项,配置文档的顶层结构如下: *注意:配置项的顺序不能颠倒,如果颠倒了它们的顺序,在MyBatis的自启动阶段会发生异常,导致程序无法运行. propertie ...
- Linkerd 2.10(Step by Step)—4. 如何配置外部 Prometheus 实例
Linkerd 2.10 系列 快速上手 Linkerd v2 Service Mesh(服务网格) 腾讯云 K8S 集群实战 Service Mesh-Linkerd2 & Traefik2 ...
- 二、特殊DNS解析
一.DNS轮询 1.为站点 www.tedu.cn 提供DNS轮询解析,三台Web服务器节点的IP地址分别为: 192.168.4.10.192.168.4.20.192.168,4.30 步骤: 虚 ...
- jmeter--JSON Extractor 用法
JMeter处理大部分请求返回的结果,都是json.对于请求返回的结果,处理以后作为其他请求的参数,有一个方便使用的插件:JSON Extractor JSON Extractor中文叫做json提取 ...