IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux中shell脚本实现多进程循环 -> 正文阅读

[系统运维]linux中shell脚本实现多进程循环

平常写shell脚本都是单个进程执行,串行执行程序,如果循环体中的逻辑与上下循环没有关联,那么可以采用多进程执行循环

类似于进程池的效果,实现代码如下:

#!/bin/bash
 
#线程池
process_pool(){
    #判断输入参数等
    if [ $# -lt 3 ]; then
        echo "$0 process_num command [args]"
        return 1
    fi
    _process_num=$1
    shift
    _func=$1
    shift
    if [[ ! $_process_num =~ ^[0-9]+$ ]]; then
        echo "process_num must be a number"
        return 1
    fi
    if !type $_func >/dev/null 2>&1; then
        echo "comannd must be executable"
        return 1
    fi
 
    # 创建一个先进先出的管道文件
    fifo="/tmp/$$.fifo"
    mkfifo $fifo
    #创建一个文件描述符号,把FD这个文件描述符关联到这个文件
    #{FD}表示非显示的描述符
    exec {FD}<>$fifo
    rm $fifo
  
 
    # 创建槽位
    for i in $(seq $_process_num); do
        echo >&$FD
    done
  
 
    # 执行具体命令
    for arg in $@; do
        read -u $FD
        {
            $_func $arg 
            echo >&$FD
        }&
    done
 
    # wait等待所有后台进程执行完成
    wait
 
    # 释放文件描述符
    exec {FD}>&-
}
 
 
#以下为测试
test(){
    echo $1
    sleep 3
    return 0
}
 
process_pool 3 'test' 1 2 3 4 5 6 7

第二种写法:

原始串行写法

#!/bin/bash

START_TIME=`date +%s`

for ((I=1;I<=10;I++))   #模拟10个任务
do
    echo "${I}: success" ; sleep 2
done

STOP_TIME=`date +%s`
echo "TIME: $(expr ${STOP_TIME} - ${START_TIME})"

并行写法1:后台执行

#!/bin/bash

START_TIME=`date +%s`

for ((I=1;I<=10;I++))
do
    {
        echo "${I}: success" ; sleep 2
    }&
done
wait

STOP_TIME=`date +%s`
echo "TIME: $(expr ${STOP_TIME} - ${START_TIME})"

并行写法2:管道+文件描述符

#!/bin/bash
THREAD_NUM=5
TMP_FILE="/tmp/$$.fifo"

trap "exec 6>&-;exec 6<&-;exit 0" 2     #脚本运行过程中,如果接收到信号2(Ctrl+C)中断命令,则关闭文件描述符6的读写,并正常退出

mkfifo ${TMP_FILE}  #创建有名管道
exec 6<>${TMP_FILE} #创建文件描述符,文件描述符可使用3-(n-1),n取值范围:ulimit -n。以读写(<,读;>,写)方式绑定TMP_FILE管道文件。标识对文件描述符6的所有操作等同于对管道文件TMP_FILE的操作
rm -rf ${TMP_FILE}  #为什么不直接使用管道文件?因为管道的一个重要特性:读写必须同时存在,缺失某个操作,另一个操作就会滞留。绑定文件描述符(读、写绑定)正好解决了这个问题

for ((J=1;J<=${THREAD_NUM};J++)) #向管道中中输入THREAD_NUM个并发数量的空行。为什么写入空行而不是字符?那是因为管道文件的读取是以行为单位。
do
    echo >&6
done

START_TIME=`date +%s`

for ((I=1;I<=10;I++))
do 
    read -u6 #从管道中读取行,每次读一行。每读一次就会减少一个空行,直到管道中没有回车符,所有行读取完毕后执行挂起,实现线程数量控制。
    {
        echo "${I}: success" ; sleep 2
        echo >&6    #任务在后台执行结束后,向文件描述符中写入一个空行。如果不在向描述符中写入空行,当后台放入THREAD_NUM个任务之后,由于描述符中没有可读取的空行,会导致read -u6停顿。
    }&
done
wait

STOP_TIME=`date +%s`
echo "TIME: $(expr ${STOP_TIME} - ${START_TIME})"
 
exec 6>&-
exec 6<&-

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-02-22 21:02:27  更:2022-02-22 21:04:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 6:03:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码