zoukankan      html  css  js  c++  java
  • 并行执行任务 Stat-Job

    最近在写一些powershell脚本时候遇到一个问题,那就是要解压十几个zip文件,这样仅执行完解压操作差不多5min的时间就过去了,严重影响了效率,这时就想到了使用多线程的方法来执行这个解压操作,经过学习了解到powershell提供了一个Start-Job命令来实现并行执行。接下来对这个命令做一个总结。


     

    一、真实案例

      以我之前遇到的问题作为示例来介绍这个命令,先贴出源方案,串行执行。c:zipfile目录下有十几个zip文件,需要对文件进行解压,按照原有的方案是遍历整个目录,一次解压,耗时5min。

    foreach ( $i in ls c:zipfile*.zip)
    {
        .7z.exe x $i 
    } 
    

      利用start-job后的代码:

    foreach ( $i in ls c:zipfile*.zip)
    {
    $command = ".7z.exe x $i" Start-Job -ScriptBlock{ $command }     #注意:在{}中不可以传入“.7z.exe x $i”类似这样命令与变量的结合体,{}接收的是类似$command这样的字符串或者是“.7z.exe x a.zip”这样的内容。否则会报错哦 }

      使用并行执行的方案后,执行时长缩小到了1min。

    二、熟练使用start-job及相关配套命令

      1、start-job  

        后台运行sleep命令,并且为这个任务命名为“sleep”。  

    Start-Job -ScriptBlock { sleep 10 } -Name sleep 
    

        在后台运行命令前首先将1赋值给$a,然后再去执行输出$a的操作,最后命名为test,-InitializationScript参数的作用是任务开始前需要执行的。

    Start-Job -InitializationScript { $a = 1 } -ScriptBlock { echo $a } -Name test
    

        若需要后台执行脚本,使用-FilePath参数即可

    Start-Job -FilePath .a.ps1
    

      2、get-job

      获取当前所有后台进程的状态信息,starte是任务的执行状态,“Completed”表示任务完成,“Failed”表示任务执行失败,“Running”表示正在运行的,“Stopped”表示任务停止。

    PS C:> Get-Job
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    29     Job29           BackgroundJob   Completed     True            localhost            mkdir  c:a...         
    31     test1           BackgroundJob   Failed        False           localhost             slepp 20                
    

      3、stop-job

      停止后台运行的某个任务,下面的例子是后台运行一个睡20s的任务,得知该任务的id是43,然后停止id=43的任务,再去查看后台任务。如果知道后台任务的名称,也可以根据名字来停止(参数是-Name)

    PS C:Usersill> Start-Job -ScriptBlock{ sleep 20}
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    43     Job43           BackgroundJob   Running       True            localhost             sleep 20                
    
    
    PS C:Usersill> Stop-Job -id 43
    
    PS C:Usersill> Get-Job
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    43     Job43           BackgroundJob   Stopped       False           localhost             sleep 20  
    

      4、receive-job

       我们在使用start-job后台执行任务的时候,往往是不会显示命令的执行结果,此时可以使用receive-job命令查看它的结果

    PS C:Usersill> Start-Job -ScriptBlock { echo "1" } -Name "ok"
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    45     ok              BackgroundJob   Running       True            localhost             echo "1"                
    
    
    
    PS C:Usersill> Receive-Job -Name ok
    1
    

      5、wait-job

      再回到最初的案例,对文件解压完后,需要将各个解压文件移动到某个位置,但是使用start-job将每个解压任务放到后台,此时系统会接着执行后续的操作,这时出现了文件还没有解压完成,就已经开始对解压文件进行操作,导致脚本异常。针对这个问题需要用到wait-job命令。

    PS C:> Start-Job -ScriptBlock { sleep 5 } -Name s1
    Start-Job -ScriptBlock { sleep 6 } -Name s2
    Start-Job -ScriptBlock { sleep 7 } -Name s3
    echo "satrt"
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    47     s1              BackgroundJob   Running       True            localhost             sleep 5                 
    49     s2              BackgroundJob   Running       True            localhost             sleep 6                 
    51     s3              BackgroundJob   Running       True            localhost             sleep 7                 
    satrt
    

      我们可以看到三个后台任务和输出“start”几乎是同时执行的,加入wait-job后

    PS C:> Start-Job -ScriptBlock { sleep 5 } -Name s1
    Start-Job -ScriptBlock { sleep 6 } -Name s2
    Start-Job -ScriptBlock { sleep 7 } -Name s3
    Wait-Job *
    echo "satrt"
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    53     s1              BackgroundJob   Running       True            localhost             sleep 5                 
    55     s2              BackgroundJob   Running       True            localhost             sleep 6                 
    57     s3              BackgroundJob   Running       True            localhost             sleep 7                 
    57     s3              BackgroundJob   Completed     False           localhost             sleep 7                                 
    55     s2              BackgroundJob   Completed     False           localhost             sleep 6                                
    53     s1              BackgroundJob   Completed     False           localhost             sleep 5                                
    satrt
    

      加入wait-job命令后的现象是,等待所有的后台命令执行完成后,才去执行echo “start”。此时就明白了wait-job的作用了,那就是等待执行的任务完成后再去执行其他的。

      其中wait-job中-Id和-Name可以指定特定的任务。

      若不用wait-job命令可以下面的代码来监控后台任务是否执行完

    Remove-Job *
    #测试计时开始
    $start_time = (Get-Date)
    
    Start-Job -ScriptBlock { sleep 9; Write-Host "Hello myJob1."; } -Name "myJob1"
    Start-Job -ScriptBlock { sleep 5; Write-Host "Hello myJob2."; } -Name "myJob2"
    $taskCount = 2
    while($taskCount -gt 0)
    {
        foreach($job in Get-Job)
        {
            $state = [string]$job.State
            if($state -eq "Completed")
            {   
                Write-Host($job.Name + " 已经完成")
                Receive-Job $job
                $taskCount--
                Remove-Job $job
            }
        }
        sleep 1
    }
    "所有任务已完成"
     
    #得出任务运行的时间
    (New-TimeSpan $start_time).totalseconds
    

      以上的作用是等待所有后台任务结束后才会执行后续的操作,还有一种参数是-Any,它的作用是等待后台任务中任意一个介绍就会执行后续操作。

    Remove-Job *
    
    Start-Job -ScriptBlock{ sleep 2 } -Name a1
    Start-Job -ScriptBlock { sleep 30} -Name a2
    Wait-Job -Any *
    

      等上述执行完成后,查看get-job,可以看到“sleep 30”还在进行。即有一个后台任务结束后就不在等待!

    PS C:Windowssystem32> Get-Job
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    115    a1              BackgroundJob   Completed     False           localhost             sleep 2                 
    117    a2              BackgroundJob   Running       True            localhost             sleep 30 
    

       6、remove-job

      删除后台运行的任务,前提条件是该后台任务是停止状态

    PS C:> Get-Job
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    53     s1              BackgroundJob   Completed     False           localhost             sleep 5                 
    55     s2              BackgroundJob   Completed     False           localhost             sleep 6                 
    57     s3              BackgroundJob   Completed     False           localhost             sleep 7                 
    59     rm              BackgroundJob   Completed     False           localhost             sleep 20                
    
    
    
    PS C:> Remove-Job -Name rm
    
    PS C:> Get-Job
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    53     s1              BackgroundJob   Completed     False           localhost             sleep 5                 
    55     s2              BackgroundJob   Completed     False           localhost             sleep 6                 
    57     s3              BackgroundJob   Completed     False           localhost             sleep 7                 
    
    
    
    PS C:> Remove-Job *
    
    PS C:> Get-Job
    

     三、start-job传入参数

       将参数传入start-job需要用到两个,一个是花括号中的param(),另一个是ArguementList,具体实例如下。

    PS C:> $a = "name"
    
    PS C:> $b = "bill"
    
    PS C:> Start-Job -ScriptBlock{ param($a,$b) echo "$a == $b" }  -ArgumentList $a,$b
    
    Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
    --     ----            -------------   -----         -----------     --------             -------                  
    67     Job67           BackgroundJob   Running       True            localhost             param($a,$b) echo "$a...
    
    
    PS C:> Receive-Job -id 67
    name == bill
    

      over!

     

     

      

     

     

  • 相关阅读:
    共享纸巾更换主板代码分析 共享纸巾主板更换后的对接代码
    Python Django Ajax 传递列表数据
    Python Django migrate 报错解决办法
    Python 创建字典的多种方式
    Python 两个list合并成一个字典
    Python 正则 re.sub替换
    python Django Ajax基础
    Python Django 获取表单数据的三种方式
    python Django html 模板循环条件
    Python Django ORM 字段类型、参数、外键操作
  • 原文地址:https://www.cnblogs.com/zqj-blog/p/10120743.html
Copyright © 2011-2022 走看看