treedown’s Report

システム管理者に巻き起こる様々な事象を読者の貴方へ報告するブログです。会社でも家庭でも"システム"に携わるすべての方の共感を目指しています。

シャットダウン中に処理が進まなくなった場合にもPsExec

デスクトップ環境(Windowsシェル)が使えない状況で、どうやってトラブルシューティングするか、一つの方法をご報告です。

昔のテレビでは調子が悪い時に本体を叩くと直る、ということがあったのですが、サーバ停止しているように見えるときにはコマンドで叩いて直してみようという感じです。
抽象的な例えはこのくらいにしておきまして…
実際にどういう局面で使ったかといいますと、シャットダウン画面がある表示で(ずっと処理中のまま進まないことがありました。(ただし応答なしではない)
もう少し具体的な環境の説明をしますと、
OSはWindows 2008 R2で、ServicePack1を適用して再起動に入るところ、
Hyper-V Virtual Machine Management をシャットダウンしています...」
と画面にメッセージが表示されてカーソルがぐるぐるして(いわゆる砂時計が回っている状態)いるが、サーバ本体のインジケータ(LED)ではHDDにアクセスしている気配もなければ、CPUが動いている気配もない、というとき、何かの要因で何か(ここではHVMM)がハングアップしていると考えていいわけです。
この"何か(ここではHVMM)"がタイムアウト待ちでタイムアウトして処理が実行されれば、根気強く待つのも一つの手ですが、実際には終わらずに何時間もその画面のまま、ということが多いです。

で、そんな時、そんなあなたに、この方法が有効です。
条件としては、RPCがシャットダウンしておらずネットワーク経由でイベントビューアの接続やサービス管理が可能な状態であることが条件です。RPC(リモートプロシージャコール)ですよ、RDP(リモートデスクトップ接続)ではありません。

まずネットワーク経由でサービス(services.msc)を起動し対象コンピュータに接続してみましょう。
service.mscを起動して「サービス(ローカル)」と記載のあるところを右クリックし「別のコンピュータへ接続」を選択、別のコンピュータ欄にコンピュータ名かIPアドレスを入力して接続します。

f:id:treedown:20150904093819p:plain

f:id:treedown:20150904093932p:plain
もしリモートコンピュータのサービス画面に接続し表示できたら、サービスの中から状態:「停止処理中」なものがないかを確認しましょう。
発見したら十中八九、そのサービスの停止が何かの理由で止まっているのが原因です。今回の例でいえば「Hyper-V Virtual Machine Management」が「停止処理中」になっていました。
プロパティ画面から実行パスをみると「C:\Windows\system32\vmms.exe」とあるのでプロセス名vmms.exeがハング(?)の原因です。
しかしServices.msc画面ではサービスを停止も強制終了もできない、状態確認はできるのですが実際のサービス操作ができなくてここで作業がストップです。

かなり昔の話にはなりますが、ServicePack繋がりで、Windows XP ServicePack3適用の際に似たような経験をしたのを思い出します。
この時はセキュリティ対策としてUSB利用制限を掛けていたPCでServicePack3を適用した時に発生しました。
当時実施していた、セキュリティ対策(USB利用制限、注※)の中で、グループポリシー経由でファイルがロック状態になっている状態でした。で、そのファイルがSP3で置き換え対象のファイルだったために、ServicePack3更新プログラムがファイル置き換えのためのアクセスができなくてServicePack3適用処理が完了しない(適用中画面のまま何時間も先に進まない)ということがありました。当時休日出勤し手作業で全台にSP適用作業をしていた私は青くなったものです。

---------------------------------------------------------------------------------------------------------
注※
USB利用制限のため、MS公式の手法で利用制限を適用すると、c:\Windows配下のファイルsffdisk.infやusbstor.dllなどのアクセス権がEveryone:アクセス拒否となるのです。
SP3ではこのsffdisk.infやusbstor.dllが更新されファイルが置き換え(上書き)られるのですが、「Everyone:アクセス拒否」なのでSP3適用時でもファイルにアクセスができない、という状況に陥りました。
---------------------------------------------------------------------------------------------------------

この場合には、デスクトップは起動しているのでイベントビューアを起動し、その原因が(エラーで)記録されているので、該当のファイルに対してアクセス権を与える処理をすればよかったものでした。

今回のパターンではシャットダウン処理中なので、当然イベントビューアといった原因を調査し解決するための操作を実行するためのコンソールがないし、中途半端に起動中(シャットダウン中)だから管理共有も使えない、ということで「こりゃ、なにもできませんや」という状態になって困ることになります。
このXPの例も含めて、ハングアップ時点でRDPサービスが使えれば話は早いのですが、SP適用時のシャットダウンプロセス時にRDP接続などできるはずもないし、ハードウェアのリモート操作では現在のコンソールが表示できるだけなので、別のセッションでデスクトップを開けるわけではないということで、最終的に攻めあぐねて電源長押し(=電プチ)で神に祈る、ことが多かったとお察しします。

こういったシャットダウン中に何かが処理中で止まってしまった場合、神頼みで電源長押しするその前に、以下の方法で接続して操作が可能かどうか確かめてみるのをお勧めしたいと思いました。
使うのは機能のこれ⇒ PsExec.exeです。
リモート接続操作最後の切り札=PSExec - treedown’s Report
このPsExec.exeを利用します。

これを問題が発生しているリモートコンピュータのコマンドプロンプトを開いて操作してしまおうというもくろみです。

では、例にあるような「Hyper-V Virtual Machine Management をシャットダウンしています...」と表記されているシチュエーションで実際に使った方法を記載します。

まずはPsExecを実行するために、バッチファイルから起動しましょう。

アクセス先:HVSVR
ドメイン名:DOM1
ユーザ名:AdmUser
バッチファイル名:psexec.bat(psexec.exeが動作すること)

-------------------------------------------------------
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\Users\AdmUser>psexec.bat
操作したいPC名かIPを入力してください >HVSVR
操作対象PCが所属するドメイン名を入力してください
ワークグループ環境ではこの欄は空欄にしてください >DOM1
.
HVSVR.DOM1にアクセスします。
.
login as:AdmUser
AdmUser@HVSVRorDOM1's password: パスワードを入力

*******ここで画面が切り替わります。*******

PsExec v1.98 - Execute processes remotely
Copyright (C) 2001-2010 Mark Russinovich
Sysinternals - www.sysinternals.com


Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>
-------------------------------------------------------
こんな感じでリモート側のコマンドプロンプトが起動します。
起動時のWindows [Version 6.3.9600]なのが、psexec.exe起動後はWindows [Version 6.1.7601]と、バージョン番号が変わっているのがお分かりになるでしょうか?バージョンが6.1.7601に変わったことで2008R2のコマンドプロンプトを開いたことが分かります。
起動後すぐにdirしてしまうとWindows\system32フォルダ内の大量のファイルを見せられることに
なり、時間がかかるので、すぐcdでc:\とルートにでも移りましょう。
リモートコンピュータのコマンドプロンプトを開いていることを確認するにはdirコマンドでフォルダ一覧を見るのが手っ取り早いです。
-------------------------------------------------------
C:\Windows\system32>cd c:\

c:\>dir
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は 7898-7DB5 です

c:\ のディレクトリ

2012/12/09  08:04               106 IBMPostCommands.cmd
2012/12/09  07:59    <DIR>          IBMSGTK
2012/12/08  16:04    <DIR>          IBM_Support
2009/07/14  12:20    <DIR>          PerfLogs
2012/12/08  16:06    <DIR>          Program Files
2012/12/08  19:14    <DIR>          Program Files (x86)
2012/12/08  18:50    <DIR>          Users
2012/12/09  15:25    <DIR>          Windows
               2 個のファイル                 652 バイト
               8 個のディレクトリ  54,697,803,776 バイトの空き領域
-------------------------------------------------------
同一画面内にも関わらず、dirで表示されるc:\のフォルダファイル一覧は遠隔地のサーバのもの、
こんな調子でコマンドが発行できるわけです。
いま知りたいのはハングアップしているサービスの実行パスにあった
「C:\Windows\system32\vmms.exe」
が、どうなっているかと状態確認するためにプロンプトを開いたので、確認しましょう。
※コマンド出力結果はいらない情報を端折っています。
-------------------------------------------------------
c:\>tasklist | more

イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
System Idle Process              0 Services                   0         24 K
System                           4 Services                   0         60 K
smss.exe                       236 Services                   0        756 K
vmms.exe                      1544 Services                   0     13,496 K
WmiPrvSE.exe                  1836 Services                   0      7,272 K
svchost.exe                   1176 Services                   0      5,768 K
LogonUI.exe                   2984 Services                   0     16,184 K
msdtc.exe                     2608 Services                   0      7,704 K
PSEXESVC.EXE                  2432 Services                   0      4,728 K
cmd.exe                       1432 Services                   0      2,972 K
conhost.exe                   1384 Services                   0      3,184 K
tasklist.exe                  2740 Services                   0      5,792 K
more.com                      1388 Services                   0      2,788 K

c:\>
-------------------------------------------------------

見つかりました。vmms.exe。PIDは1544でセッション名がServicesなのでサービスとして稼働している。
テレビを叩く、に近い方法としてこの原因となっているプロセスを切ってしまいましょう。
-------------------------------------------------------
c:\> taskkill /IM vmms.exe
指定されたプログラムは実行できません。
-------------------------------------------------------
上記が実際に遭遇した時の画面です、エラーっぽくなっていますがタスクは正常に落せていました。
停止の原因になっていたプロセスが終了したのでシャットダウンプロセスが進行しました。なので
-------------------------------------------------------
c:\>tasklist
Error communicating with PsExec service on ix36-05.vsn.co.jp:
指定されたネットワーク名は利用できません。
-------------------------------------------------------
切れたことをtasklistコマンドで確認してもエラーになってしまいました。シャットダウン処理をせき止めていたサービスを停止することによって再開したOSシャットダウンによって、OSが停止してしまったからです。

と、こうして、(画面素材は取れませんでしたが)停止したプロセスを落とすことができました。

少々話が脱線します。
taskkillコマンドを知っている人なら気づくかもしれませんが、
「taskkillはリモートシステムのタスクを落とせるのでpsexecを使う必要がない。」
という考え方もあります。(使ったことありませんが)実際にオプションにあります。
--------------------------------------------------------
c:\>taskkill /?

TASKKILL [/S システム [/U ユーザー名 [/P [パスワード]]]]
         { [/FI フィルター] [/PID プロセスID | /IM イメージ名] } [/T] [/F]
パラメーター一覧:
    /S    システム            接続するリモート システムを指定します。

    /U    [ドメイン\]ユーザー コマンドが実行されるユーザー コンテキストを
                              指定します。
…省略
--------------------------------------------------------
ただ、あくまでコマンドがリモートシステムへの干渉ができるかどうか、を知識として知っていないと、できるかどうかが分からない、というところがポイントです。
psexecでコマンドプロンプトを開けば、その知識が不要になるのは一つのメリットです。
このためローカルファイルのNTFSアクセス権を操作するcaclsだって余裕で操作ができます。
ちょっと脱線しますが、XP SP3の適用時に発生した前出の停止の事例でいえば、、、
PSexecで接続したのち、そのコマンドプロンプト内で、
--------------------------------------------------------
c:\>cacls "c:\windows\inf\sffdisk.inf" /E /R Everyone
--------------------------------------------------------
これだけ。あとはイベントビューアでsffdisk以外にも同様のエラーになっていないか確認して、
--------------------------------------------------------
c:\>cacls "c:\windows\inf\usbstor.dll" /E /R Everyone
--------------------------------------------------------
てな具合に続けてやっていくと終わるのです。

このローカルかリモートか、気にせずにリモートのコマンドプロンプトが開けるというssh経由でのCUIコンソールのごとき使いやすさが緊急時にぴったり来るわけです。

この書き込みがだれかの役に立つと幸いです。

バッチファイルをお使いの場合には最後に
--------------------------------------------------------
c:\>exit
cmd exited on HVSVR with error code 0.
ログアウトし切断します。

C:\Users\AdmUser>
--------------------------------------------------------
exitで終了するのはお忘れなく。