該当プロセスのチェック→終了する処理や関数化を行い、(個人的にスクリプトが)見やすい状態に修正。
しかし、書き方が悪かったためか、スクリプト ファイルに記述した関数をリモート先で実行できない事が判明。
今回は、Invoke-Command コマンドレットのScriptBlock オプションに関数を記述し実行する方法+αをメモ。
色々な手法があるかもしれません、ご紹介するスクリプトは一例だと思ってくださいね。
サンプル
サンプル内容は、「PowerShell 手動追加したサービスをリモートから再起動するスクリプト」のスクリプトを修正したものです。環境等は上記リンクを参照願います。
Invoke-Command コマンドレットのScriptBlock オプションに関数を記述・実行する場合は
- リモートで実行したい関数をラップする($func1 = {~}の記述)
- リモート先に接続(New-PSSession ~)
- ラップ関数を実行する(Invoke-Command ~ -ScriptBlock $func1)
- 同上、メイン関数を実行する(Invoke-Command ~ -ScriptBlock {~})
<# ------------------------------------------------------------------- 【 PS名 】 ScanSnap用サービス再起動スクリプト 【バージョン 】 1.1.0.0 ------------------------------------------------------------------- #> $func1 = { function Reset-PfuServices() { Write-Host "サーバ接続 OK!!!" Write-Host "操作を開始します" #変数セット $fileFolder = "x:\ServerFolders\スキャンフォルダ" $ServiceName1 = "PfuSsMon" $ServiceName2 = "PfuSsWiaChecker" #サービス停止 Stop-Service $ServiceName1 -Force Stop-Service $ServiceName2 -Force Write-Host " →サービスを停止しました" #プロセス終了 # - 補足:サービス停止時に[PfuSsMon.exe]は終了するが、稀にプロセスが残り続ける場合あります。 # - 本処理はその場合に強制終了させる処理です。 $prcess = Get-Process | where{ $_.ProcessName -eq $ServiceName1 } if($process -ne $null) { Stop-Process -ProcessName $ServiceName1 -Force Write-Host " →プロセス「PfuSsMon」を削除しました" } #一時ファイル削除 Set-Location $fileFolder $cnt = (gci .\*pd~ | measure).Count if($cnt -gt 0) { Remove-Item .\*pd~ -Force Write-Host " →一時ファイルを削除しました" } #サービス開始 Start-Service $ServiceName1 Start-Service $ServiceName2 Write-Host " →サービス開始しました" #サーバ切断 Write-Host "全ての操作が完了しました" } } [string]$serverName = "xxxx" [string]$adminUser = "administrator" [string]$adminPwd = "P@ssword" #資格認証 if($adminPwd -ne ""){ $password = ConvertTo-SecureString $adminPwd -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential("$serverName\$adminUser",$password) } else{ $credential = "$serverName\$adminUser" } #接続 $s = New-PSSession -ComputerName $serverName -Credential $credential #ラップ関数実行 Invoke-Command -Session $s -ScriptBlock $func1 #メイン関数実行 Invoke-Command -Session $s -ScriptBlock{ Reset-PfuServices } #切断 Remove-PSSession -Session $s
メイン関数を記述した ps1 ファイルを実行する手もある!
当初、メイン関数の実行をInvoke-Command -Session $s -ScriptBlock {function:Reset-PfuServices}のように記述しましたが、失敗に終わりました。
理由は、リモート先に[Reset-PfuServices]関数が存在していないからです。
マイクロソフト エバンジェリスト 安納さんのブログで図解入りで説明されています。
すごくわかりやすいので、是非記事を読んでみてください。
【PowerShell】Invole-Command –FilePath パラメタの魔法(フィールドSEあがりの安納です)安納さんが説明されている通り、メイン関数を記述したps1 ファイルをリモート先に送信、実行する方法も試してみました。
問題なく実行できますね!
関数を使いまわす場合は、スクリプト ファイル(.ps1)にしてしまった方が便利かな。
スクリプト ファイル(.ps1)のサンプル
Write-Host "サーバ接続 OK!!!" Write-Host "操作を開始します" #変数セット $fileFolder = "D:\ServerFolders\スキャンフォルダ" $ServiceName1 = "PfuSsMon" $ServiceName2 = "PfuSsWiaChecker" #サービス停止 Stop-Service $ServiceName1 -Force Stop-Service $ServiceName2 -Force Write-Host " →サービスを停止しました" #プロセス終了 # - 補足:サービス停止時に[PfuSsMon.exe]は終了するが、稀にプロセスが残り続ける場合あります。 # - 本処理はその場合に強制終了させる処理です。 $prcess = Get-Process | where{ $_.ProcessName -eq $ServiceName1 } if($process -ne $null) { Stop-Process -ProcessName $ServiceName1 -Force Write-Host " →プロセス「PfuSsMon」を削除しました" } #一時ファイル削除 Set-Location $fileFolder $cnt = (gci .\*pd~ | measure).Count if($cnt -gt 0) { Remove-Item .\*pd~ -Force Write-Host " →一時ファイルを削除しました" } #サービス開始 Start-Service $ServiceName1 Start-Service $ServiceName2 Write-Host " →サービス開始しました" #サーバ切断 Write-Host "全ての操作が完了しました"
実行スクリプト
[string]$serverName = "xxxx"
[string]$adminUser = "administrator"
[string]$adminPwd = "P@ssword"
#資格認証
if($adminPwd -ne ""){
$password = ConvertTo-SecureString $adminPwd -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential("$serverName\$adminUser",$password)
}
else{
$credential = "$serverName\$adminUser"
}
#接続
$s = New-PSSession -ComputerName $serverName -Credential $credential
#関数実行
Invoke-Command -Session $s -FilePath "x:\SampleScript.ps1"
#切断
Remove-PSSession -Session $s