Bash shell 中,三种子 shell 实践

2024-01-19 03:18
文章标签 实践 shell bash 种子

本文主要是介绍Bash shell 中,三种子 shell 实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Bash shell 中,三种子 shell 实践

一 背景

让我们先来看一下下面这个简单的例子:

#!/bin/bash
#===============================================================================
#          FILE: process_test.sh
#         USAGE: . ${YOUR_PATH}/process_test.sh
#   DESCRIPTION:
#        AUTHOR: IVAN DU
#        E-MAIL: mrivandu@hotmail.com
#        WECHAT: ecsboy
#      TECHBLOG: https://ivandu.blog.csdn.net
#        GITHUB: https://github.com/mrivandu
#       CREATED: 2019-05-01 23:56:32
#       LICENSE: GNU General Public License.
#     COPYRIGHT: © IVAN DU 2019
#      REVISION: v1.0
#===============================================================================test_num=${RANDOM};
echo "Test start. Current process is: $$. Parent process is: ${PPID}. Test_num is: ${test_num}. ";
# &
{
echo '-----------&------------';
echo "& test start. test_num is: ${test_num} ";
sleep 30
echo "& test. Now pid is:$$";
test_num=${RANDOM}
echo "& test_num is: ${test_num}. ";
}&
echo "& test end. Test_num is: ${test_num}. ";
# |
echo ""|\
{
echo '-----------|------------';
echo "| test start. test_num is: ${test_num} ";
sleep 30
echo "| test. Now pid is:$$";
test_num=${RANDOM}
echo "| test_num is: ${test_num}. ";
}
echo "| test end. Test_num is: ${test_num}. ";
# ()
(
echo '-----------()------------';
echo "() test start. test_num is: ${test_num} ";
sleep 30
echo "() test. Now pid is:$$";
test_num=${RANDOM}
echo "() test_num is: ${test_num}. ";
)
echo "() test end. Test_num is: ${test_num}. ";
echo "All tests stop. Parent process is: $$. Test_num is: ${test_num}.";

这个例子展示了三种创建子 shell 的方法,每个子 shell 的内容基本都一致。接下来让我们看一下执行结果:

[gysl@gysl-dev ~]$ sh process_test.sh
Test start. Current process is: 10432. Parent process is: 6118. Test_num is: 1457.
& test end. Test_num is: 1457.
-----------&------------
& test start. test_num is: 1457
-----------|------------
| test start. test_num is: 1457
& test. Now pid is:10432
& test_num is: 26453.
| test. Now pid is:10432
| test_num is: 17987.
| test end. Test_num is: 1457.
-----------()------------
() test start. test_num is: 1457
() test. Now pid is:10432
() test_num is: 28781.
() test end. Test_num is: 1457.
All tests stop. Parent process is: 10432. Test_num is: 1457.

二 分析求证

执行该脚本的当前 shell 的 PID 是 6118 ,也就是当前 shell 的 PPID 。脚本开始时,我们使用一个随机数对 test_num 进行了赋值,在当前脚本中的值是 1457 。在三种子 shell 的执行过程中,test_num 传入了子 shell ,依然为 1457 。子 shell 中再次对 test_num 赋值能覆盖传入的 test_num 的值,但子shell 执行完毕之后,返回的值依然为 1457 。三种方式都出奇的的一致,这说明:子 shell 在执行过程中能引用父 shell 的变量,父 shell 中的变量在子 shell 中被修改后不返回父 shell ,作用域只存在于子 shell 中。简而言之,父 shell 中的值能被子 shell 调用,父 shell 中的变量能被子 shell 修改,子 shell 中的变量值不能传回父 shell 。

继续分析,“& test end. Test_num is: 1457. ”出现在第二行,这一行原本是在 & 子 shell 执行完毕后才执行的,但是却提前执行了。进一步观察,我们发现,& 子 shell 和 | 子 shell 的执行结果混在一起了。而 () 子 shell 却中规中矩的按照预期执行。这是为什么呢?让我们来看一下 pstree 命令返回的结果:

[gysl@gysl-dev ~]$ pstree -c -p 6118
bash(6118)───sh(10432)─┬─sh(10433)───sleep(10436)└─sh(10435)───sleep(10437)
[gysl@gysl-dev ~]$ pstree -c -p 6118
bash(6118)───sh(10432)───sh(10439)───sleep(10440)

当前 shell 10432 在执行初期,先后产生了两个子 shell,30 秒后,这两个子 shell 执行结束,执行 () 子 shell 。结果显而易见,& 子 shell 支持异步执行!

三 总结

3.1 实现子 shell 的方式有三种:&/|(管道)/()。

3.2 子 shell 能调用并修改父 shell 的变量值,但是子 shell 的变量值不返回父 shell 中,要牢记。

3.3 & 方式实现的子 shell 能异步执行,这是与其他两种实现方式最大的不同之处。

这篇关于Bash shell 中,三种子 shell 实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/621112

相关文章

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

Spring Boot统一异常拦截实践指南(最新推荐)

《SpringBoot统一异常拦截实践指南(最新推荐)》本文介绍了SpringBoot中统一异常处理的重要性及实现方案,包括使用`@ControllerAdvice`和`@ExceptionHand... 目录Spring Boot统一异常拦截实践指南一、为什么需要统一异常处理二、核心实现方案1. 基础组件

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

Linux中shell解析脚本的通配符、元字符、转义符说明

《Linux中shell解析脚本的通配符、元字符、转义符说明》:本文主要介绍shell通配符、元字符、转义符以及shell解析脚本的过程,通配符用于路径扩展,元字符用于多命令分割,转义符用于将特殊... 目录一、linux shell通配符(wildcard)二、shell元字符(特殊字符 Meta)三、s

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬