はじめに
本記事で扱うPowershellの並列処理は「マルチプロセス」ではないです。
同一プロセス中で
- Copy-Item
- Move-Item
といったシーケンシャルな動作をするコマンドや、
function Start-MyFunc{...}
c:\work\Start-MyFunc.ps1
といった自作関数などを並列に動作させたい場合について記載します。
また、本記事でのPowershellはv4.0を利用しています。
単純な並列処理
workflow Copy-AllItem {
ForEach -parallel ($count in @(0..99)){
Copy-Item -path "hogehoge" -destination "fugafuga$count"
}
}
# 実行
Copy-AllItem
これで100件のコピー処理が並列に動作し(たように見え)ます。
もちろん(ほとんど)同時に処理が開始されただけです。
実際にはCopy-Itemの実行完了を待たず、次のCopy-Itemを実行しているだけです。
ですが、実際にはこんな簡単な処理を並列で動作させるケースは稀です。
おそらくは引数で配列を渡すケースが多いでしょう。
引数をもとに並列処理を実行
workflow Copy-AllItem {
param(
$counts
)
ForEach -parallel ($count in $counts){
Copy-Item -path "hogehoge" -destination "fugafuga$count"
}
}
# 実行
Copy-AllItem -counts @(0..99)
はい。普通にパラメーターとして設定してあげればよいです。
ここで幾つか試された方は気付くと思います。
自作関数でForEach -Parallelを実行すると怒られます。
「InlineScriptとして定義しろ」だのと言われ、実際にInlineScript{}で囲むと、今度は「引数が読めない」と怒られます。
う~んこまった。
自作関数をInlineScriptとして並列処理するときに引数を読み込ませる方法
workflow Copy-AllItem {
param(
[PSObject[]]
$items
)
ForEach -parallel ($item in $items){
InlineScript{ C:\work\Start-MyCopyFunc.ps1 -path $Using:item.fullname -destination $Using:item.destination }
}
}
# 実行
Copy-AllItem -items MyObjects
InlineScriptで怒られたときは「$Using:変数名」にしましょう。
もっと詳しく知りたい人は以下の記事を参照。
PowerShell における Windows Workflow Foundation 4.0 (WF) 利用のすすめ
まだまだある課題
workflow Copy-ItemInVsphere {
param(
[PSObject[]]
$items
)
ForEach -parallel ($item in $items){
InlineScript{ Copy-DatastoreItem "vmstore:\$Using:item.fullname" "c:\work\$Using:item.name"}
}
}
# 実行
Copy-ItemInVsphere -items MyObjects
といったように、PowerCLIで動作させようとしたら「Copy-DatastoreItemなぞ知らん」と怒られました。
workflowオブジェクトの中でPowerCLIモジュールを読み込ませる処理が必要なのだろうか。。
今のところ未解決案件。
- 以上 -