LinuxからWindowsにバッチでファイルを定期的に移動する方法(逆もできるよ!)
やりたいこと*1
ファイルをバックアップするときなど、LinuxからWindowsへ、WindowsからLinuxへファイルをコピーや 移動したい場合があります。
いろいろ方法はあると思うのですが、WinSCPでは.NET Assemblyが公開されているので使ってみることにしました。
必要なもの
説明
C#で作ろうかと思ったのですが、簡単にかけるPowerShellで作りました。 こちらの例では、Linuxのサーバ(sessionOptions.HostNameに指定)にあるファイルをWindowsのPC(PowerShellが動いているPC)に移動してます。
なお、パスワード(sessionOptions.Password)がコメントアウトしてあるのはpagentを用いてSSH鍵認証を行っているためです。必要であればパスワードを書いてください。
ほぼWinSCPのサイトにあるサンプルのままですけど(^_^)
try { # Load Windows Form [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") # Load WinSCP .NET assembly (パスは環境によって変更してください) [Reflection.Assembly]::LoadFrom("C:\Program Files\WinSCP\WinSCPnet.dll") | Out-Null # Setup session options $sessionOptions = New-Object WinSCP.SessionOptions $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp $sessionOptions.HostName = "【接続先ホスト名】" $sessionOptions.UserName = "【ユーザ名】" #$sessionOptions.Password = "【パスワード】" $sessionOptions.SshHostKeyFingerprint = "【フィンガープリント 例: ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx】" $session = New-Object WinSCP.Session try { # Connect $session.Open($sessionOptions) # Upload files バイナリモードを設定 $transferOptions = New-Object WinSCP.TransferOptions $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary #リモートマシンの"/tmp/backup/*"を"C:\tmp\backup\"に「移動」。 3つめの引数を$FALSEにするとコピー $transferResult = $session.GetFiles("/tmp/backup/*","C:\tmp\backup\", $TRUE, $transferOptions) # Throw on any error $transferResult.Check() # Print results foreach ($transfer in $transferResult.Transfers) { Write-Host ("Download of {0} succeeded" -f $transfer.FileName) } } finally { # Disconnect, clean up $session.Dispose() } exit 0 } catch [Exception] { #エラーが出たらダイアログを出して気がついてもらう [System.Windows.Forms.MessageBox]::Show($_.Exception.Message, "バックアップエラー!",[Windows.Forms.MessageBoxButtons]::OK,[Windows.Forms.MessageBoxIcon]::Error); exit 1 }
後日追記
PowerShellをVersion3にしたところ、[Reflection.Assembly]::LoadFrom("C:\Program Files\WinSCP\WinSCPnet.dll") でエラーが出るようになった。
ファイルまたはアセンブリ 'file:///C:\Program Files\WinSCP\WinSCPnet.dll'、またはその依存関係の 1 つが読み込 めませんでした。操作はサポートされません。 (HRESULT からの例外:0x80131515)
さっぱり原因がわかりませんでしたが、WinSCPのフォーラムで意外な解決策が提示されてました。 Topic "Powershell : Could not load file or assembly winscp.dll"
[Reflection.Assembly]::LoadFrom("C:\Program Files\WinSCP\WinSCPnet.dll")
を
[Reflection.Assembly]::LoadFrom("\\C:\Program Files\WinSCP\WinSCPnet.dll")
に・・・ファイルパスの前に"\\"追加したら動きました。
もっと後日追記(2018/07/20)
久々にPCを入れ替えたら実行されなくなっていた。いろいろ調べた結果、dllファイルの「ブロック解除」が必要でした。