WinRM(Windows リモート管理 )

PowerShell

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-PSSession1つまたは複数の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

参考サイト

Linux からの WinRM アクセスを許可する
PowerShellをリモートコンピューターで実行 - マイクロソフト系技術情報 Wiki
リモート コンピューターの対話操作(Enter-PSSession)
PowerShell リモート処理 - PowerShell
PowerShell でリモート コンピューターに対してコマンドを実行するには、さまざまな方法があります。
リモートトラブルシューティングについて - PowerShell
PowerShell でリモート操作のトラブルシューティングを行う方法について説明します。
PowerShell を使用して Windows VM に接続する  |  Compute Engine  |  Google Cloud Documentation
Windows リモート管理のインストールと構成 - Win32 apps
Windows リモート管理スクリプトを実行し、Winrm ツールでデータ操作を実行するために、Windows リモート管理をインストールして構成する方法について説明します。

コメント