前提条件
WinRM (Windows Remote Management)を有効にする
Get-Item WSMan:\localhost\Listener\*\Port
# PowerShellを管理者として実行
Enable-PSRemoting
# 強制的に起動する場合は
Enable-PSRemoting -Force
※ Windows2012R2の場合はデフォルトで有効になっていますので設定する必要はありません。
※ WinRMを有効にすることで,ファイアウォールの5985番ポートがオープンします。
# ネットワークがプライベートでない場合は
Enable-PSRemoting -SkipNetworkProfileCheck
クライアント側で管理者権限で WinRM を起動
net start WinRM
構成設定の状態を確認
winrm get winrm/config
TrustedHostsを設定する
# PowerShellを管理者として (ホスト名 or IPアドレス or *)を追加
# ホストは(private, domain)ネット上の名前、もしくはIPアドレスで設定
Set-Item WSMan:\localhost\Client\TrustedHosts -Value (ホスト名 or IPアドレス or *)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "操作される側のIP"
WinRMでは,接続元のホストから見て,接続先のホストが「信頼できるホストである」ことが必要です.
接続元のホストから,次のコマンドを実行
# 複数のホスト名やIPアドレスを設定する場合
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "host1, host2"
# ホストを信頼ホストリストに追加する(クライアント)
# 元のホストリストhost.domain,hoge.fugaにnew.hostを追加
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "host.domain,hoge.fuga,new.host"
# すべてのホストを信頼する場合
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*"
# 現在設定されているTrustedHostsを確認
Get-Item WSMan:\localhost\Client\TrustedHosts
# 設定されているTrustedHostsをすべて消去
Clear-Item WSMan:\localhost\Client\Trustedhosts
実装
フォルダ構成
FileCopy.
│ ConfigFileCopy.json
│ FileCopy.ps1
│
└─log
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
* バージョン :
* 作成者 :
* 作成日 :
* 更新者 :
* 更新日 :
*
"@ -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
$RemoteOutdir = 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
$RemoteOutdir
$indir = $config.from_server.from_path
$filenames = $config.from_server.file_name
if(Test-Path -LiteralPath $indir ){
# 対象ファイを取得し、コピー先サーバーのディレクトリへコピー
$exclude_array_name = New-Object System.Collections.Generic.List[string]
$filelists = Get-ChildItem -LiteralPath $indir | Where-Object {$_.Name -In $filenames }
$filelists | ForEach-Object {
$exclude_array_name.Add($_.Name + "_*")
$outfile = $outdir + "\" + $_.Name + "_" + $datetime
Copy-Item -LiteralPath $_.FullName -Destination $outfile -Recurse
Write-Host "[INFO] $infile から $outfile をコピーしました。"
}
}
} catch [Exception]{
Write-Host 'リモートPCへの接続エラー OR ファイルコピーのエラー。'
Write-Host $Error
}
try{
# コピー先のディレクトリで6世代以上保持し、最も日付が古いものは削除
# 更新日降順にソートし、-First 指定で、先頭何個まで取得
$exclude_array = (Get-ChildItem -LiteralPath $outdir -Include $exclude_array_name |
Sort-Object -Property { $_.LastWriteTime} -Descending |
Select-Object -First (6 * $filenames.Length)).Name
Remove-Item "${outdir}\*" -Exclude $exclude_array -Recurse
Write-Host "$(Get-Date -Format g) $exclude_array 以外ファイルを削除"
# "${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
ConfigFileCopy.json JSONファイル内容
[
{
"from_server": {
"from_path": "C:\\Users\\Use\\Desktop\\サーバーAディレクトリ",
"file_name": ["test.DMP", "test_USR", "testsize"]
},
"to_server": {
"user": "test.local\\user",
"pass": "password",
"host": "ホスト名",
"to_path": "C:\\Users\\Use\\Desktop\\サーバーBディレクトリ"
}
}
]
PowerShellをリモートコンピューターで実行 - マイクロソフト系技術情報 Wiki
Linux からの WinRM アクセスを許可する

PowerShell リモート処理 - PowerShell
PowerShell でリモート コンピューターに対してコマンドを実行するには、さまざまな方法があります。

リモートトラブルシューティングについて - PowerShell
PowerShell でリモート操作のトラブルシューティングを行う方法について説明します。
コメント