热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

取文件shell_理解Shell脚本中的多进程和多线程并发,让工作效率提升1000倍

背景日常运维工作中编写shell脚本处理事务,很多时候需要一次性处理很多,需要用到循环,但是循环体内还是线性的,还是要一个个

背景

日常运维工作中编写shell脚本处理事务,很多时候需要一次性处理很多,需要用到循环,但是循环体内还是线性的,还是要一个个处理,这样并不会节省很多时间,只是节省了人工一次次输入的繁琐。但是对于提高处理能力,没有实质性的提高。这就需要考虑并发。但Shell中并没有真正意义的多线程,要实现多线程可以启动多个后端进程,最大程度利用cpu性能。即:多进程并发,本篇教程由浅入深详细介绍了shell中的多进程并发。

8221bde22d0986233c5e1be9a69b6cdb.png

范例

#!/bin/bashtrap "exec 1000>&-;exec 1000testfiform -fr testfifofor((n&#61;1;n<&#61;10;n&#43;&#43;))do echo >&1000donestart&#61;&#96;date "&#43;%s"&#96;for((i&#61;1;i<&#61;100;i&#43;&#43;))do read -u1000 { echo "success $i"; sleep 5 echo >&1000 }&donewaitend&#61;&#96;date "&#43;%s"&#96;echo "Time: &#96;expr $end - $start&#96;"exec 1000>&-exec 1000

实验

所谓的多进程只不过是将多个任务放到后台执行而已&#xff0c;很多人都用到过&#xff0c;所以现在讲的主要是控制&#xff0c;而不是实现。

实验一

先看一个小shell&#xff1a;

06e17bf99ff7411bd9106e5719b125dc.png

看执行结果&#xff1a;

295256af1d45d111c9ebdb412517fa43.png

很明显是8s&#xff0c;这种不占处理器却有很耗时的进程&#xff0c;我们可以通过一种后台运行的方式
来达到节约时间的目的。

实验二

如下为改进&#xff1a;

4d6c1caddd32ddf20ffdb366a7b0574b.png

用“{}”将主执行程序变为一个块&#xff0c;用&放入后台&#xff0c;四次执行全部放入后台后&#xff0c;我们需要用一个wait指令&#xff0c;等待所有后台进程执行结束&#xff0c;不然 系统是不会等待的&#xff0c;直接继续执行后续指令&#xff0c;知道整个程序结束。
看结果&#xff1a;

7f1fde4494587f26f3675cc81f6d2328.png

可以看到&#xff0c;时间已经大大缩短了&#xff01;

实验三

以上实验虽然达到了多线程并发的目的&#xff0c;但有一个缺陷&#xff0c;不能控制运行在后台的进程数。为了控制进程&#xff0c;我们引入了管道 和文件操作符。

无名管道&#xff1a; 就是我们经常使用的 例如&#xff1a; cat text | grep “abc” 那个“|”就是管道&#xff0c;只不过是无名的&#xff0c;可以直接作为两个进程的数据通道
有名管道&#xff1a; mkfilo 可以创建一个管道文件 &#xff0c;例如&#xff1a; mkfifo fifo_file

管道有一个特点&#xff0c;如果管道中没有数据&#xff0c;那么取管道数据的操作就会停滞&#xff0c;直到管道内进入数据&#xff0c;然后读出后才会终止这一操作&#xff0c;同理&#xff0c;写入管道的操作&#xff0c;如果没有读取操作&#xff0c;这一个动作也会停滞。

ab545d65247e3849821799826adf8258.png

当我们试图用echo想管道文件中写入数据时&#xff0c;由于没有任何进程在对它做读取操作&#xff0c;所以它会一直停留在那里等待读取操作&#xff0c;此时我们在另一终端上用cat指令做读取操作

4424b80a9ff12cc9c07b194eec4fdbc5.png

你会发现读取操作一旦执行&#xff0c;写入操作就可以顺利完成了&#xff0c;同理&#xff0c;先做读取操作也是一样的&#xff1a;

04f71c3b8c4db7fcbff55d44628a5317.png

由于没有管道内没有数据&#xff0c;所以读取操作一直滞留在那里等待写入的数据

91e061bb33e71769770640c9055a627a.png

一旦有了写入的数据&#xff0c;读取操作立刻顺利完成

以上实验&#xff0c;看以看到&#xff0c;仅仅一个管道文件似乎很难实现 我们的目的(控制后台线程数), 所以 接下来介绍 文件操作符&#xff0c;这里只做简单的介绍&#xff0c;如果不熟悉的可以自行查阅资料。
系统运行起始&#xff0c;就相应设备自动绑定到了 三个文件操作符 分别为 0 1 2 对应 stdin &#xff0c;stdout&#xff0c; stderr 。
在 /proc/self/fd 中 可以看到 这三个三个对应文件

c71e765e8e08c57c63c0cf771c071a95.png

输出到这三个文件的内容都会显示出来。只是因为显示器作为最常用的输出设备而被绑定。

我们可以exec 指令自行定义、绑定文件操作符&#xff0c;文件操作符一般从3–(n-1)都可以随便使用
此处的n 为 ulimit -n 的定义值得

3e2a561ea6540d1d71fc365e8054ecba.png

可以看到 我的 n值为1024 &#xff0c;所以文件操作符只能使用 0-1023&#xff0c;可自行定义的 就只能是 3-1023 了。

直接上代码&#xff0c;然后根据代码分析每行代码的含义&#xff1a;

89b609d8758befea0e9373748963346c.png

代码解释

第3行&#xff1a; 接受信号 2 (ctrl &#43;C)做的操作。exec 1000>&-和exec 1000testfifo 来实现&#xff0c;但关闭时必须分开来写&#xff0c;> 读的绑定&#xff0c;<标识写的绑定 <> 则 标识 对文件描述符 1000的所有操作等同于对管道文件testfifo的操作。

第5-7行&#xff1a;分别为 创建管道文件&#xff0c;文件操作符绑定&#xff0c;删除管道文件
     可能会有疑问&#xff0c;为什么不能直接使用管道文件呢&#xff1f; 
     事实上&#xff0c;这并非多此一举&#xff0c;刚才已经说明了管道文件的一个重要特性了&#xff0c;那就是读写必须同时存在
     缺少某一种操作&#xff0c;另一种操作就是滞留&#xff0c;而绑定文件操作符 正好解决了这个问题。

第9-12 行&#xff1a; 对文件操作符进行写入操作。通过一个for循环写入10个空行&#xff0c;这个10就是我们要定义的后台线程数 量。
为什么写入空行而不是10个字符呢 &#xff1f;
这是因为&#xff0c;管道文件的读取 是以行为单位的。

39001ae8f1c725df30c820252a247cdf.png

当我们试图用 read 读取管道中的一个字符时&#xff0c;结果是不成功的&#xff0c;而刚才我们已经证实使用cat是可以 读取的。

第17-24行&#xff1a;这里假定我们有100个任务&#xff0c;我们要实现的时 &#xff0c;保证后台只有10个进程在同步运行 。read -u1000 的 作用是&#xff1a;读取一次管道中的一行&#xff0c;在这儿就是读取一个空行。减少操作附中的一个空行之后&#xff0c;执行一 次任务(当然是放到后台执行)&#xff0c;需要注意的是&#xff0c;这个任务在后台执行结束以后会向文件操作符中写 入一个空行&#xff0c;这就是重点所在&#xff0c;如果我们不在某种情况某种时刻向操作符中写入空行&#xff0c;那么结果就 是&#xff1a;在后台放入10个任务之后&#xff0c;由于操作符中没有可读取的空行&#xff0c;导致 read -u1000 这儿 始终停顿。

后边的 就不用解释了。

贴下执行结果&#xff1a;

2d744765b35156d17aa25196fbf9181b.png

每次的停顿中都能看到 只有10个进程在运行
一共耗时50s 一共100个任务&#xff0c;每次10个 &#xff0c;每个5s 正好50s。上边的结果图之所以这么有规律&#xff0c;这是因为我们所执行的100个任务耗时都是相同的。

比如&#xff0c;系统将第一批10个任务放入后台的过程所消耗的时间 几乎可以忽略不计&#xff0c;也就是说这10个任务几乎可以任务是同时运行&#xff0c;当然也就可以认为是同时结束了&#xff0c;而按照刚才的分析&#xff0c;一个任务结束时就会向文件描述符写入空行&#xff0c;既然是同时结束的&#xff0c;那么肯定是同时写入的空行&#xff0c;所以下一批任务又几乎同时运行&#xff0c;如此循环下去的。实际应用时&#xff0c;肯定不是这个样子的&#xff0c;比如&#xff0c;第一个放到后台执行的任务&#xff0c;是最耗时间的&#xff0c;那他肯定就会是最后一个执行完毕。所以&#xff0c;实际上来说&#xff0c;只要有一个任务完成&#xff0c;那么下一个任务就可以被放到后台并发执行了。



推荐阅读
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 技术日志:Ansible的安装及模块管理详解 ... [详细]
  • 本文介绍了如何创建和运行一个简单的 Bash 脚本,包括创建脚本文件、编写输出指令、赋予执行权限和运行脚本的基本步骤。 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • 性能测试中的关键监控指标与深入分析
    在软件性能测试中,关键监控指标的选取至关重要。主要目的包括:1. 评估系统的当前性能,确保其符合预期的性能标准;2. 发现软件性能瓶颈,定位潜在问题;3. 优化系统性能,提高用户体验。通过综合分析这些指标,可以全面了解系统的运行状态,为后续的性能改进提供科学依据。 ... [详细]
  • Java并发机制详解及其在数据安全性保障中的应用方案 ... [详细]
  • 数字图书馆近期展出了一批精选的Linux经典著作,这些书籍虽然部分较为陈旧,但依然具有重要的参考价值。如需转载相关内容,请务必注明来源:小文论坛(http://www.xiaowenbbs.com)。 ... [详细]
  • Python全局解释器锁(GIL)机制详解
    在Python中,线程是操作系统级别的原生线程。为了确保多线程环境下的内存安全,Python虚拟机引入了全局解释器锁(Global Interpreter Lock,简称GIL)。GIL是一种互斥锁,用于保护对解释器状态的访问,防止多个线程同时执行字节码。尽管GIL有助于简化内存管理,但它也限制了多核处理器上多线程程序的并行性能。本文将深入探讨GIL的工作原理及其对Python多线程编程的影响。 ... [详细]
  • 在开发过程中,我最初也依赖于功能全面但操作繁琐的集成开发环境(IDE),如Borland Delphi 和 Microsoft Visual Studio。然而,随着对高效开发的追求,我逐渐转向了更加轻量级和灵活的工具组合。通过 CLIfe,我构建了一个高度定制化的开发环境,不仅提高了代码编写效率,还简化了项目管理流程。这一配置结合了多种强大的命令行工具和插件,使我在日常开发中能够更加得心应手。 ... [详细]
  • 在嵌入式Linux系统中,性能低下通常由CPU、内存和I/O三个关键因素引起。为了有效提升系统性能,首先需要识别并定位性能瓶颈。通过综合分析这些瓶颈,可以采取针对性的优化措施,如调整内核参数、优化算法和改进数据结构等,从而显著提高系统的整体性能。 ... [详细]
  • MySQL 8.0 MGR 自动化部署与配置:DBA 和开源工具的高效解决方案
    MySQL 8.0 MGR 自动化部署与配置:DBA 和开源工具的高效解决方案 ... [详细]
  • Linux Shell变量初探:初始值解析与使用指南
    本文探讨了Linux Shell中变量的基本概念及其在BASH中的应用。变量是用于存储可变数据的标识符,能够代表不同的值。文章详细介绍了BASH shell的主要优势,包括强大的命令编辑能力、自动补全功能、命令别名设置、作业控制以及前后台任务管理。此外,还涵盖了编程脚本编写和通配符的使用方法,为初学者提供了全面的指导。 ... [详细]
author-avatar
手机用户2602915205
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有