【bat】バッチファイルで複数PCに一括コマンドを送信する方法(psexec活用)

bat

Windows環境で複数台のPCに対して一括でコマンドを実行したいとき、Sysinternals の PsExec は手軽で強力なツールです。リモートでコマンドを実行したり、ファイルを配布してプロセスを起動したり、ログを収集したりといった運用作業をバッチファイルで自動化できます。本記事では PsExec の前提、基本コマンド、ホスト一覧を読み込んで一括実行するバッチ例、実運用での注意点と代替手段までを実践的にまとめます。

前提と準備

PsExec を使うには以下が必要です。事前に環境を確認してください。
– Sysinternals PsExec(psexec.exe)をダウンロードし、実行可能なパス(例: C:\tools\psexec\)に置く(管理者権限での実行を推奨)。
– 実行ユーザーがリモート側で管理者権限を持つこと(ローカル管理者またはドメイン管理者)。
– リモートPCで管理共有(\\TARGET\C$)が利用可能であること。SMB/ファイル共有がブロックされていると失敗する。
– リモート側のファイアウォールが必要な通信(SMB、Remote Service)を許可していること。
– 初回は PsExec のライセンス受諾が必要(-accepteula を付けることで自動受諾)。
企業ポリシーやセキュリティルールでリモート実行が制限されている場合は事前に管理者と調整してください。

PsExec の基本オプション(よく使うもの)

  • psexec \\host cmd — リモートでコマンドを実行
  • -u user / -p pass — 認証情報を指定(パスワードは平文になるため注意)
  • -s — System 権限で実行
  • -i — インタラクティブセッションで実行(デスクトップが必要な GUI 実行など)
  • -c — ローカルの実行ファイルをリモートにコピーして実行
  • -d — デタッチ(非同期で実行してすぐ戻る)
  • -n <秒> — タイムアウト(指定秒数を待って接続をあきらめる)
  • -accepteula — 初回ライセンス確認を自動承諾

単純な手動実行例

:: リモートで単純な dir を実行して結果をホスト側に表示
C:\tools\psexec\psexec.exe \\pc01 -u DOMAIN\admin -p P@ssw0rd cmd /c "dir C:\Windows\System32"

ホスト一覧ファイルを読み込んで一括実行するバッチ(同期実行)

ホスト一覧(hosts.txt)を用意し、for /f で順次処理します。結果は個別ログに保存します。平文パスワードを避けたい場合はドメイン認証で実行するか、実行ユーザーでログインして実行してください。

@echo off
setlocal enableextensions enabledelayedexpansion

:: 設定
set "PSEXEC=C:\tools\psexec\psexec.exe"
set "HOSTS=hosts.txt"          :: ホスト名 or FQDN を改行で列挙
set "USER=DOMAIN\admin"        :: ドメインの管理者アカウント(省略時は現在ユーザー)
set "PASS=YourPasswordHere"    :: セキュリティ上の注意:平文保存は避ける
set "REMOTE_CMD=ipconfig /all" :: 実行したいコマンド
set "OUTDIR=logs"

if not exist "%OUTDIR%" mkdir "%OUTDIR%"

for /f "usebackq tokens=*" %%H in ("%HOSTS%") do (
  echo === Processing %%H ===
  "%PSEXEC%" \\%%H -accepteula -u "%USER%" -p "%PASS%" -n 30 cmd /c "%REMOTE_CMD%" > "%OUTDIR%\%%H.txt" 2>&1
  if errorlevel 1 (
    echo [ERROR] %%H >> "%OUTDIR%\summary.txt"
  ) else (
    echo [OK] %%H >> "%OUTDIR%\summary.txt"
  )
)

echo Done. See %OUTDIR% for per-host outputs.
endlocal
pause

バッチ内でファイルを配布して実行する(-c を使用)

実行ファイルやスクリプトをリモートへコピーして実行するパターン。たとえば更新スクリプト updater.bat を各ホストで実行する。

@echo off
setlocal

set "PSEXEC=C:\tools\psexec\psexec.exe"
set "HOSTS=hosts.txt"
set "USER=DOMAIN\admin"
set "PASS=YourPassword"
set "LOCAL_SCRIPT=updater.bat"

for /f "usebackq tokens=*" %%H in ("%HOSTS%") do (
  echo Deploying to %%H ...
  "%PSEXEC%" \\%%H -accepteula -u "%USER%" -p "%PASS%" -c "%LOCAL_SCRIPT%" -n 60 > "logs\deploy_%%H.log" 2>&1
)

endlocal
pause

並列(並行)実行の実装例(start /b を活用)

大量台数を直列で実行すると時間がかかるため、Windows バッチの start /b で並列実行できます。※並列数は環境に応じて制限を入れるのが安全。

@echo off
setlocal

set "PSEXEC=C:\tools\psexec\psexec.exe"
set "HOSTS=hosts.txt"
set "USER=DOMAIN\admin"
set "PASS=YourPassword"
set "REMOTE_CMD=whoami && hostname"
set "OUTDIR=logs"
set /a "MAX_PARALLEL=10"

if not exist "%OUTDIR%" mkdir "%OUTDIR%"

set /a running=0
for /f "usebackq tokens=*" %%H in ("%HOSTS%") do (
  rem 並列実行
  start /b cmd /c "%PSEXEC% \\%%H -accepteula -u %USER% -p %PASS% -n 30 cmd /c \"%REMOTE_CMD%\" > %OUTDIR%\%%H.txt 2>&1"
  set /a running+=1

  rem 簡易スロット制御(MAX_PARALLELを超えたら待つ)
  if !running! geq %MAX_PARALLEL% (
    rem wait for a short while(改善: より厳密なジョブ監視を実装する)
    timeout /t 3 /nobreak >nul
    set /a running=0
  )
)

echo Started parallel tasks. Check %OUTDIR% for output.
endlocal
pause

※上記は簡易的な制御です。より厳密に「並列ジョブ数」を管理するには PowerShell の Start-Job / Wait-Job を使うほうが安定します(後述)。

ログとリターンコードの扱い

PsExec はリモートで起動したプロセスの標準出力/標準エラーをローカルに返しますが、リターンコードの取り扱いは注意が必要です。バッチで errorlevel をチェックして失敗を集計するパターンを必ず入れましょう。実行ログはホスト毎に分けておくと、障害切り分けが楽になります。

セキュリティと運用上の注意点

– 平文パスワードの保存は避ける(可能ならドメインアカウントで実行する、または Windows Credential Manager や別の安全な vault を利用)。
– PsExec は SMB を使うため、ネットワーク経路のセキュリティに注意。VPN/社内ネットワーク外からの接続は適切に制限する。
– UAC・LocalAccountTokenFilterPolicy によりローカルアカウントのリモート権限が制限されることがある(管理者でも落とし穴あり)。ドメイン環境ではドメイン管理者アカウントを使用するのが安定。
– AV/EDR が PsExec をブロックする場合がある。事前に運用ポリシーを確認。
– 管理者権限での実行はリスクを伴うため、実行内容をログに残し、実行履歴を監査可能にすること。
– 大規模環境やセキュア環境では、PsExec より WinRM/PowerShell Remoting(Kerberos認証)を推奨する場合が多い(より細かな権限制御と暗号化が標準で使える)。

トラブルシューティングのヒント

– 「Access denied」や接続失敗:アカウントの権限、管理共有の有効化、SMBやファイアウォール設定を確認。
– 「Could not start PsExec service on remote system」:サービス作成に失敗している(権限不足やAVによる阻害)。ログを参照し、手動でサービスが作成できるか確認。
– UAC による制限:リモートからローカル管理者権限を扱う際に LocalAccountTokenFilterPolicy の調整が必要なケースあり(組織ポリシーに相談)。
– 速度が遅い/大量に失敗する:ネットワーク帯域、認証の負荷、並列数を見直す。並列実行は控えめに。

より安全な代替:PowerShell Remoting(Invoke-Command)

セキュリティと柔軟性を重視するなら PowerShell Remoting(WinRM)を検討します。Kerberos や NTLM による認証、リモートセッションの管理、スクリプトブロック実行、並列ジョブ管理などが標準でサポートされます。たとえば PowerShell なら次のように一括実行できます(バッチから pwsh を呼ぶ形でも連携可能)。

# PowerShell 例(簡略)
$hosts = Get-Content hosts.txt
Invoke-Command -ComputerName $hosts -Credential (Get-Credential) -ScriptBlock { ipconfig /all } | Out-File logs\pwsh_results.txt

実運用でのベストプラクティスまとめ

– まずはテスト環境で少数ホストから確認し、問題点(ファイアウォール、AV、UAC)を洗い出す。
– Cred 管理は平文ファイルを避け、安全な方法(ドメイン認証、Credential Manager、Vault)を使う。
– ホスト一覧や実行コマンド、実行ログは必ず保存して監査できるようにする。
– 大量台数は PowerShell の並列機構や管理ツール(SCCM, Intune, Ansible/WinRM)を検討する。
– 自動化スクリプトには乾坤一擲のコマンド(del /s /q 等)を慎重に扱うガード(確認や –dry-run ロジック)を入れる。

まとめ

PsExec を使えば Windows 環境で手軽に複数PCへ一括コマンドを送信できます。バッチファイルでホスト一覧を読み取り、個別ログを残しつつ順次または並列に実行することで、運用作業の自動化が進みます。ただし認証やネットワーク、UAC、アンチウイルスといった実運用のハードルがあるため、事前検証とセキュリティ対策を必ず行ってください。より安全でスケーラブルな運用が必要なら PowerShell Remoting や構成管理ツールの導入も検討しましょう。