PowerShellを使わずにWinRMでコマンド実行する

背景

社内で使っているWindows10の共有端末のなかにバッチが置いてあって業務の中で頻繁に叩く必要がある。現状では皆がリモートデスクトップ接続して実行しており、色々鬱陶しいのでいい加減やめたかった。

ログイン情報は基本的に社内の全員が知っているぐらいの勢いなので秘匿する必要なし。

クライアントはWindows7か10でPowerShellが入ってなかったりPATH通ってなかったりもする。

手順

サーバ側

  • PowerShellを管理者権限で実行する
  • WinRMを有効化する
winrm qc
  • PowerShellのウィンドウを閉じてもう一度管理者権限で開き直す(何故か分からないが必要だった)
  • Basic認証と平文を許可する
# Basic認証
winrm set winrm/config/service/auth '@{Basic="true"}'

# 平文
winrm set winrm/config/service '@{AllowUnencrypted="true"}'

これでサーバー側は完了です。Firewallの穴あけとか別途必要な場合はあるかもしれません。

クライアントのツールを作る

今回はクライアントにPowerShell入ってない場合があるのと、PowerShell入ってたとしてもWindows7をサポートしようとすると色々面倒なのと、そもそも自分のWindows10でIPアドレス指定でHTTP経由のWinRMへの接続がうまく行かなかったのとでPythonでやっちゃったほうが早いという結論に達しました。
今回はPythonでWinRMクライアントとして動くスクリプトを作成した上で、py2exeを使ってexe化して配布しています。

Pythonでクライアントツールを作成

  • Pythonをインストール(Pythonは32bit版だとpy2exeで作る配布物を1つのexeにまとめることができるのでお薦めです)
    今回は2.7の32bit版をインストールしました。 www.python.org
  • pywinrmをインストール
pip install pywinrm
#!/usr/bin/env python
import winrm
import sys
s = winrm.Session(sys.argv[1], auth=(sys.argv[2], sys.argv[3]))
r = s.run_cmd(sys.argv[4], sys.argv[5:])
print r.std_out
python winrmclient.py 192.168.1.1 username password dir

作ったスクリプトをexeにする

from distutils.core import setup
import py2exe

option = {
  "compressed" : 1,
  "optimize" : 2,
  "bundle_files" : 1,
  "include" : ["winrm"]
}

setup(
  options = {
    "py2exe" : option
  },
  console = [
    {"script"   :    "winrmclient.py"}
  ],
  zipfile = None
)
  • exeを作成
python setup.py py2exe
  • distフォルダの中にできたexeをテスト
winrmclient.exe 192.168.1.1 username password dir

完成です。こいつをbatから呼び出して使う予定です。