अद्यतन - जबकि यह उत्तर पावरशेल रनवे की प्रक्रिया और यांत्रिकी की व्याख्या करता है और कैसे वे आपको बहु-सूत्र गैर-अनुक्रमिक कार्यभार में मदद कर सकते हैं, साथी PowerShell aficionado Warren 'Cook मॉन्स्टर' F ने अतिरिक्त मील चला गया है और इन समान अवधारणाओं को एक एकल उपकरण में शामिल किया है। कहा जाता है - यह वही करता है जिसका मैं नीचे वर्णन करता हूं, और उसने तब से इसका विस्तार किया है, जिसमें आयातित मॉड्यूल सहित लॉगिंग और तैयार सत्र राज्य के लिए वैकल्पिक स्विच, वास्तव में अच्छा सामान - मैं दृढ़ता से अनुशंसा करता हूं कि आप इसे स्वयं चमकदार समाधान बनाने से पहले इसकी जांच करें !Invoke-Parallel
समानांतर रनस्पेस निष्पादन के साथ:
अपरिहार्य प्रतीक्षा समय को कम करना
मूल विशिष्ट मामले में, निष्पादन योग्य आह्वान में एक /nowait
विकल्प होता है, जो नौकरी करते समय चालान थ्रेड को ब्लॉक करने से रोकता है (इस मामले में, समय पुन: सिंक्रनाइज़ेशन) अपने आप ही समाप्त हो जाता है।
यह जारीकर्ता के दृष्टिकोण से समग्र निष्पादन समय को बहुत कम कर देता है, लेकिन प्रत्येक मशीन से कनेक्ट करना अभी भी अनुक्रमिक क्रम में किया जाता है। अनुक्रम में हजारों ग्राहकों से जुड़ने के लिए मशीनों की संख्या के आधार पर एक लंबे समय के लिए लग सकता है जो एक कारण या किसी अन्य दुर्गम के कारण होता है, टाइमआउट इंतजार की एक संचय के कारण।
एक एकल या कुछ लगातार टाइमआउट के मामले में बाद के सभी कनेक्शनों को कतारबद्ध करने के लिए, हम समानांतर में निष्पादित करते हुए, PowerShell Runspaces को अलग करने के लिए कमांड कनेक्ट करने और आह्वान करने का काम भेज सकते हैं।
एक रनस्पेस क्या है?
एक रनस्पेस एक वर्चुअल कंटेनर है जिसमें आपका पावरशेल कोड निष्पादित करता है, और पावरस्ले स्टेटमेंट / कमांड के परिप्रेक्ष्य से पर्यावरण का प्रतिनिधित्व करता है / रखता है।
व्यापक रूप से, 1 रनस्पेस = निष्पादन का 1 धागा, इसलिए हम सभी को "मल्टी-थ्रेड" की आवश्यकता होती है हमारी पॉवरशेल स्क्रिप्ट रनस्पेस का एक संग्रह है जो तब समानांतर में निष्पादित कर सकती है।
मूल समस्या की तरह, कई रनवे को कमांड देने का काम टूट सकता है:
- एक RunspacePool बनाना
- एक PowerShell स्क्रिप्ट या रनस्पेसपूल के लिए निष्पादन योग्य कोड का एक समान टुकड़ा असाइन करना
- कोड को असिंक्रोनस रूप से इनवॉइस करें (यानी कोड के वापस आने का इंतजार न करें)
RunspacePool टेम्पलेट
[RunspaceFactory]
पॉवरशेल में एक प्रकार का त्वरक होता है, जो हमें रनस्पेस घटकों के निर्माण में सहायता करेगा - चलो इसे काम करने के लिए रखें
1. एक RunspacePool बनाएँ और Open()
इसे:
$RunspacePool = [runspacefactory]::CreateRunspacePool(1,8)
$RunspacePool.Open()
दो तर्कों को पारित किया गया CreateRunspacePool()
, 1
और 8
किसी भी समय निष्पादित करने के लिए अनुमत न्यूनतम और अधिकतम संख्या में रनस्पेस है, जिससे हमें 8 के समानांतर अधिकतम प्रभावी डिग्री प्राप्त हुई ।
2. PowerShell का एक उदाहरण बनाएं, इसके लिए कुछ निष्पादन योग्य कोड संलग्न करें और इसे हमारे RunspacePool में असाइन करें:
PowerShell का एक उदाहरण powershell.exe
प्रक्रिया के समान नहीं है (जो वास्तव में एक होस्ट अनुप्रयोग है), लेकिन निष्पादित करने के लिए PowerShell कोड का प्रतिनिधित्व करने वाला एक आंतरिक रनटाइम ऑब्जेक्ट। हम [powershell]
PowerShell के भीतर एक नया PowerShell उदाहरण बनाने के लिए प्रकार त्वरक का उपयोग कर सकते हैं :
$Code = {
param($Credentials,$ComputerName)
$session = New-PSSession -ComputerName $ComputerName -Credential $Credentials
Invoke-Command -Session $session -ScriptBlock {w32tm /resync /nowait /rediscover}
}
$PSinstance = [powershell]::Create().AddScript($Code).AddArgument($creds).AddArgument("computer1.domain.tld")
$PSinstance.RunspacePool = $RunspacePool
3. APM का उपयोग करते हुए PowerShell उदाहरण को अतुल्यकालिक रूप से शामिल करें:
.NET डेवलपमेंट शब्दावली में एसिंक्रोनस प्रोग्रामिंग मॉडल के रूप में जो ज्ञात है उसका उपयोग करके , हम Begin
कोड को निष्पादित करने के लिए "हरी बत्ती" और End
परिणामों को इकट्ठा करने के लिए एक विधि के लिए एक कमांड के आह्वान को एक विधि में विभाजित कर सकते हैं । चूंकि हम इस मामले में वास्तव में किसी भी प्रतिक्रिया में रुचि नहीं रखते हैं (हम w32tm
वैसे भी आउटपुट से इंतजार नहीं करते हैं ), हम केवल पहली विधि को कॉल करके बना सकते हैं
$PSinstance.BeginInvoke()
इसे एक RunspacePool में लपेटकर
उपरोक्त तकनीक का उपयोग करते हुए, हम नए कनेक्शन बनाने और एक समानांतर निष्पादन प्रवाह में दूरस्थ कमांड को लागू करने के अनुक्रमिक पुनरावृत्तियों को लपेट सकते हैं:
$ComputerNames = Get-ADComputer -filter * -Properties dnsHostName |select -Expand dnsHostName
$Code = {
param($Credentials,$ComputerName)
$session = New-PSSession -ComputerName $ComputerName -Credential $Credentials
Invoke-Command -Session $session -ScriptBlock {w32tm /resync /nowait /rediscover}
}
$creds = Get-Credential domain\user
$rsPool = [runspacefactory]::CreateRunspacePool(1,8)
$rsPool.Open()
foreach($ComputerName in $ComputerNames)
{
$PSinstance = [powershell]::Create().AddScript($Code).AddArgument($creds).AddArgument($ComputerName)
$PSinstance.RunspacePool = $rsPool
$PSinstance.BeginInvoke()
}
यह मानते हुए कि सीपीयू में एक ही समय में सभी 8 रनस्पेस को निष्पादित करने की क्षमता है, हमें यह देखने में सक्षम होना चाहिए कि निष्पादन का समय बहुत कम है, लेकिन उपयोग किए गए "उन्नत" तरीकों के कारण स्क्रिप्ट की पठनीयता की कीमत पर।
समानता की अधिकतम डिग्री का निर्धारण:
हम एक रनस्पेसपूल आसानी से बना सकते हैं जो एक ही समय में 100 रनस्पेस के निष्पादन की अनुमति देता है:
[runspacefactory]::CreateRunspacePool(1,100)
लेकिन दिन के अंत में, यह सब नीचे आता है कि हमारे स्थानीय सीपीयू निष्पादन की कितनी इकाइयों को संभाल सकते हैं। दूसरे शब्दों में, जब तक आपका कोड निष्पादित हो रहा है, तब तक अधिक रनवे की अनुमति देने का कोई मतलब नहीं है, क्योंकि आपके पास कोड के निष्पादन को भेजने के लिए तार्किक प्रोसेसर हैं।
WMI के लिए धन्यवाद, यह सीमा निर्धारित करने के लिए काफी आसान है:
$NumberOfLogicalProcessor = (Get-WmiObject Win32_Processor).NumberOfLogicalProcessors
[runspacefactory]::CreateRunspacePool(1,$NumberOfLogicalProcessors)
यदि, दूसरी ओर, आप जिस कोड को निष्पादित कर रहे हैं, वह नेटवर्क विलंबता जैसे बाहरी कारकों के कारण बहुत प्रतीक्षा समय को पूरा करता है, तब भी आप तार्किक प्रोसेसर की तुलना में अधिक साथ-साथ रन-वे चलाने से लाभ उठा सकते हैं, इसलिए आप शायद परीक्षण करना चाहते हैं ब्रेक- इवन खोजने के लिए अधिकतम संभव रनस्पेस की सीमा :
foreach($n in ($NumberOfLogicalProcessors..($NumberOfLogicalProcessors*3)))
{
Write-Host "$n: " -NoNewLine
(Measure-Command {
$Computers = Get-ADComputer -filter * -Properties dnsHostName |select -Expand dnsHostName -First 100
...
[runspacefactory]::CreateRunspacePool(1,$n)
...
}).TotalSeconds
}