WinRM(Windows リモート管理、Windows Remote Management )は別なコンピュータをリモート操作することができる仕組みです。
WS-Management プロトコルを実装し、Windows OS以外(例えばUnix)などにも接続ができます。
リモート操作するだけでなく、別なコンピュータからシェルを実行できるなどでとても便利な機能です
WinRMを使用するための準備
- ホストの設定(リモートされる側)
- クライアントの設定(リモートする側)
リモートされる側(Windowsサーバ[ホスト]) WinRMを有効
PowerShellを管理者として実行
Enable-PSRemoting
# ネットワークがプライベートでない場合は
Enable-PSRemoting -SkipNetworkProfileCheck
#強制的に起動する場合は
Enable-PSRemoting -Force
※ Windows2012R2の場合はデフォルトで有効になっていますので設定する必要はありません。
リモートする側(WindowsPC[クライアント]) WinRMを有効
# PowerShellを管理者として実行
Enable-PSRemoting
# うまく動かない場合は
winrm quickconfig
# 下記コマンドが自動で流れる場合があります。
Enable-PSRemoting -Force
WinRM は要求を受信するように更新されました。
WinRM サービスの種類を正しく変更できました。
WinRM サービスが開始されました。
WinRM はリモート管理用に更新されました。
WinRM ファイアウォールの例外を有効にしました。
ローカル ユーザーにリモートで管理権限を付与するよう LocalAccountTokenFilterPolicy を構成しました。
localhostへのリモート
# 自分のPCに接続(loacalhost)する場合は
Enter-PSSession -ComputerName localhost
接続すると[localhost]となり、リモートできていることが分かります
# リモートから抜けるとき
Exit-PSSession
TrustedHostsの確認と設定
TrustedHostsの確認
Get-Item WSMan:\localhost\Client\TrustedHosts
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client Type Name SourceOfValue Value ---- ---- ------------- ----- System.String TrustedHosts
設定されていないことが分かります。
TrustedHostsの設定
すべて対象にするには
Set-Item WSMan:\localhost\Client\TrustedHosts -Value *
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client Type Name SourceOfValue Value ---- ---- ------------- ----- System.String TrustedHosts *
個別に対応するには
Set-Item WSMan:\localhost\Client\TrustedHosts -Value 接続先のIPアドレス1
Set-Item WSMan:\localhost\Client\TrustedHosts -Value “接続先のIPアドレス1,接続先のIPアドレス2”
解除するには
Clear-Item WSMan:\localhost\Client\Trustedhosts
コマンドをリモートで投げる
別なPCにあるプログラム実行したい場合は、WinRSコマンドを使用します。
winrs -r:接続先のIPアドレス -u:接続先ユーザID -p:接続先パスワード コマンド
(例)winrs -r:192.168.100.1 -u:Administrator -p:xxxxx d:\bat\test.bat
WiinRMを無効にする(使用を止めるとき)
Trustedhostsの解除
Clear-Item WSMan:\localhost\Client\Trustedhosts
WinRMを無効にする
Disable-PSRemoting
WinRMリスナーポートの確認
Get-Item WSMan:\localhost\Listener\*\Port
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Listener\Listener_1084132640 Type Name SourceOfValue Value ---- ---- ------------- ----- System.String Port 5985
WinRM ポートTCP 5985
WinRMを使用するにはファイアウォールで「ポート5985」が開いていることが必要です。
PSSessionのコマンドレット
| コマンド名 | 使用用途 |
|---|---|
| Connect-PSSession | 切断されたセッションに再接続するコマンド |
| Disconnect-PSSession | セッションから切断するコマンド |
| Enter-PSSession | リモートコンピューターと対話形式のセッションを開始するコマンド |
| Exit-PSSession | リモートコンピューターと対話形式のセッションを終了する |
| Get-PSSession | ローカルおよびリモートコンピューター上のPowerShellセッションを取得する |
| New-PSSession | ローカルまたはリモートコンピューターへの永続的なコネクションを作成するコマンド |
| Receive-PSSession | 切断されたセッションのコマンド結果を取得する |
| Remove-PSSession | 1つまたは複数のPowerShellセッションを閉じる |
| Export-PSSession | 他のセッションのコマンドをエクスポートし、PowerShellモジュールに保存する。 |
| Import-PSSession | 他のセッションのコマンドを現在のセッションにインポートする。 |
フォルダ構成
FileCopy.
│ ConfigFileCopy.json
│ FileCopy.ps1
│
└─log
ConfigFileCopy.json
[
{
"from_server": {
"from_path": "C:\\Users\\user\\Desktop\\サーバーA遷移元",
"file_name": ["TEST.DMP", "TEST", "TESTsize"]
},
"to_server": {
"user": "×××.local\\user",
"pass": "password",
"remoteHost": "ホスト名",
"to_path": "C:\\Users\\Use\\Desktop\\サーバーB遷移先"
}
}
]
FileCopy.ps1
# 変数
$username = $env:USERNAME
$hostname = hostname
$datetime = Get-Date -f 'yyyyMMddHHmmss'
$logdir = "$PSScriptRoot/log/"
$logfilename = "${username}-${hostname}-${datetime}-FileCopy.log"
# ログ記込み開始
Start-Transcript "${logdir}${logfilename}" -append
Write-Host @"
*********************************************************
*
* FileCopy Script / FileCopy.ps1
* バージョン : 1
* 作成者 :
* 作成日 :
* 更新者 :
* 更新日 :
*
"@ -ForeGroundColor green
# 設定ファイルの読み込み
Write-Host "$(Get-Date -Format g) 設定ファイル読み込み : $($PSScriptRoot)/ConfigFileCopy.json"
$config = Get-Content "$PSScriptRoot/ConfigFileCopy.json" -Encoding UTF8 | ConvertFrom-Json
# TrustedHostsの確認
$arrayTrustedHosts = New-Object System.Collections.ArrayList
$TrustedHosts = $TrustedHosts = (Get-Item WSMan:\localhost\Client\TrustedHosts).Value
$TrustedHosts
if($TrustedHosts -ne "*" ){
# 含まれるない場合
if(($TrustedHosts -notcontains $config.to_remote_server.remoteHost)){
$arrayTrustedHosts.Add($TrustedHosts)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value $arrayTrustedHosts
}
}elseif ($null -eq $TrustedHosts) {
Set-Item WSMan:\localhost\Client\TrustedHosts -Value $TrustedHosts
}
# パスワードを暗号化
$password = ConvertTo-SecureString $config.to_remote_server.pass -AsPlainText -Force
Write-Host "$(Get-Date -Format g) パスワードを暗号化 : " $password
# 非対話型認証作成
$Credential = New-Object System.Management.Automation.PSCredential ($config.to_remote_server.user, $password)
Write-Host "$(Get-Date -Format g) 非対話型認証作成 : " $Credential
try{
# PSセッションを作成
$PSsession = New-PSSession -ComputerName $config.to_remote_server.remoteHost -Credential $Credential
Write-Host "$(Get-Date -Format g) PSセッションを作成 : " $PSsession
# リモートでクライアントにあるPSを実行
$outdir = $config.to_remote_server.to_path
Invoke-Command -Session $PSsession -Scriptblock{
if (-not (Test-Path -LiteralPath $args[0])){
New-Item -LiteralPath $args[0] -ItemType Directory -Force
Write-Host "[INFO] コピー先ディレクトリ $outdir を作成しました。"
}
} -ArgumentList $outdir
$indir = $config.from_server.from_path
$filenames = $config.from_server.file_name
if(Test-Path -LiteralPath $indir ){
# 対象ファイを取得し、コピー先サーバーのディレクトリへコピー
$filelists = Get-ChildItem -LiteralPath $indir | Where-Object {$_.Name -In $filenames }
$filelists | ForEach-Object {
$infile = $_.FullName
$outfile = $outdir + "\" + $_.Name + "_" + $datetime
Copy-Item -LiteralPath $infile -Destination $outfile -Recurse
Write-Host "[INFO] $infile から $outfile をコピーしました。"
}
}
} catch [Exception]{
Write-Host 'リモートPCへの接続エラー OR ファイルコピーのエラー。'
Write-Host $Error
}
try{
# "${username}-${hostname}-${datetime}-FileCop.log"以外の logファイルを削除
Remove-Item "${logdir}\*" -Exclude ${logfilename} -Recurse
Write-Host "$(Get-Date -Format g) ${logfilename} 以外ファイルを削除"
} catch [Exception]{
Write-Host 'ファイル削除にエラーが発生しました。'
Write-Host $Error
}
# Write-Host "`r`n**セッション切断**" -ForeGroundColor green
Remove-PSSession $PSsession
# ログ出力終了
Stop-Transcript
参考サイト




コメント