16boke - 一路博客

Shell实现多线程

由于shell是单线程的,要想实现“多线程”可以通过在后台运行多进程的方式来实现。在bash中,使用后台任务来实现任务的“多进程化”。在不加控制的模式下,不管有多少任务,全部都后台执行。也就是说,在这种情况下,有多少任务就有多少“进程”在同时执行。我们就先实现第一种情况:

实例一:正常情况脚本

# !/bin/bash  
for  ((i = 0 ;i < 5 ;i ++ )); do 
{
    sleep   3 ;echo  1 >> aa  &&  echo  " done! " 
} 
done
wait 
cat aa | wc  - l
rm aa

这种情况下,程序顺序执行,每个循环3s,共需15s左右。

$  time  bash test . sh 
 done ! 
 done ! 
 done ! 
 done ! 
 done ! 
 5 

 real    0m15 . 030s
 user    0m0 . 002s
 sys     0m0 . 003s

实例二:“多进程”实现

# !/bin/bash 
for  ((i = 0 ;i < 5 ;i ++ )); do 
{
    sleep   3 ;echo  1 >> aa  &&  echo  " done! " 
} & 
done
wait 
cat aa | wc  - l
rm aa

这个实例实际上就在上面基础上多加了一个后台执行&符号,此时应该是5个循环任务并发执行,最后需要3s左右时间。

$  time  bash test . sh 
 done ! 
 done ! 
 done ! 
 done ! 
 done ! 
 5 

 real    0m3 . 011s
 user    0m0 . 002s
 sys     0m0 . 004s

效果非常明显。

这里需要说明一下wait的左右。wait是等待前面的后台任务全部完成才往下执行,否则程序本身是不会等待的,这样对后面依赖前面任务结果的命令 来说就可能出错。例如上面wc -l的命令就报错:不存在aa这个文件。

wait命令的官方解释如下:

wait [n]

Wait for the specified process and return its termination status.  n may be a process ID or  a  job  specification; if a job spec is given, all processes in that job's pipeline are waited for.  If n is not given, all currently active child processes are waited for, and the return status is zero.  If  n  specifies  a  non-existent process  or job, the return status is 127.  Otherwise, the return status is the exit status of the last processor job waited for.

实例:在75服务器上运行脚本,将其它各台的指定目录下的日志文件通过scp命令拉取回来,如果使用默认单线程的方式,则只能等到第一台服务器拉取完之后才开始第二台服务器的拉取操作,如果采用多进程的方式则会同时拉取所有服务器的文件

#!/bin/bash
date
datestr=$(date -d "yesterday" "+%Y%m%d")

rm -rf /home/web_log/vasd/logs/*

mkdir -p /home/web_log/vasd/logs/21
mkdir  /home/web_log/vasd/logs/22
mkdir /home/web_log/vasd/logs/23
mkdir /home/web_log/vasd/logs/73
mkdir /home/web_log/vasd/logs/75
mkdir /home/web_log/vasd/logs/77
mkdir /home/web_log/vasd/logs/82
mkdir /home/web_log/vasd/logs/89


scp -P5044 zengyc@192.168.113.21:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/21/ &
scp -P5044 zengyc@192.168.113.22:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/22/ &
scp -P5044 zengyc@192.168.113.23:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/23/ &
scp -P5044 zengyc@192.168.113.73:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/73/ &
#scp -P5044 zengyc@192.168.113.75:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/75/
cp /data/criusserver/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/75/ &
scp -P5044 zengyc@192.168.113.77:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/77/ &
scp -P5044 zengyc@192.168.113.82:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/82/ &
scp -P5044 zengyc@192.168.113.89:/usr/local/crius_server/logs/${datestr}/vasd-*.log /home/web_log/vasd/logs/89/ &

date
wait


Shell