プロが教える店舗&オフィスのセキュリティ対策術

サーバAから、サーバBに置いてあるvbsファイル(Apache停止が書かれている)を実行して、サーバBのApacheを停止したいのですが、うまくいきません。
サーバBで単体でそのvbsファイルを実行すると、Apacheは正常に停止します。
 戻り値は、0(プロセス完了)が帰ってきていて、接続はうまくいっているようなのですが、vbsファイルが実行されていないようです。
 非常に困っておりまして、どなたか教えていただけないでしょうか?

vbsファイルの実行のところが間違っているのかなと思うのですが・・・(今まだ会社にいないので、会社でのソースそのままではないですが、同じような感じです)
--------------------------------------------
Option Explicit

Dim strComputer
Dim strUser
Dim strPassword
Dim strBAT

' -----------------------------------
' 環境設定
' -----------------------------------
strComputer = "サーバーB"
strUser = "username"
strPassword = "password"
strBAT = "c:\hoge.bat"

' -----------------------------------
' コマンド実行
' -----------------------------------
Dim objWbemLocator
Dim objWMIService
Dim objWin32_Process
Dim errReturn
Dim intProcessID

Const WbemAuthenticationLevelPktPrivacy = 6


' リモートに接続
Set objWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objwbemLocator.ConnectServer _
(strComputer, "root\cimv2", strUser, strPassword)

objWMIService.Security_.authenticationLevel = WbemAuthenticationLevelPktPrivacy

' Win32_Process クラスを生成
Set objWin32_Process = objWMIService.Get("Win32_Process")

errReturn = objWin32_Process.Create _
("cmd.exe /cscript C:\tmp\ApacheStop.vbs", Null, Null, intProcessID)
WScript.Quit(errReturn )


もともとの要件は、機能ごとに分けたvbsファイル(Apache停止、Windows再起動、ファイルバックアップなど)を、各サーバで実行するというものです。その制御は、ひとつのバックアップサーバーで行います。

A 回答 (3件)

正式なコードではないということなので細かいミスは無視する方向で。



1.実行アカウントについて
実行するユーザーアカウントは、接続するユーザーアカウントと異なるのですか?
異なるのであれば問題ありません。
同じであれば、この記述は冗長です。

2.実行する実体について
C:\tmp\ApacheStop.vbs はこのスクリプトを実行するサーバー側に保存されていますか?

3.cscript は cmd を使わなくても実行できますよ。

4.イベントログの失敗の監査を有効にしてみてください。
 実行に失敗すると、セキュリティログかどこかに記録されるかもしれません。
 objWin32_Process.Create 以外のところで問題があれば記録されます。

この回答への補足

junkUserさん

 お早いご回答ありがとうございます!
 初めてこのような質問の書き込みをしましたが、こんなにお早い
ご回答をいただけるとは思っておりませんでした。

 とても助かります。

 cscript C:\tmp\~.vbsでやってみたら、ひとまずvbsファイルが動きました(Apacheの停止は確認できました)。 ありがとうございます。

 ただ、依然としてしくみをほとんど分かっていない状態です。。
 リモートで実行されたvbsファイルからの戻り値の取得について、知っていることがございましたら教えていただけないでしょうか?

1.実行アカウントについて
実行するユーザーアカウントは、接続するユーザーアカウントと同じで、また、パスワードも同じです。

2.実行する実体について
C:\tmp\ApacheStop.vbs はこのスクリプトを実行するサーバー側に保存しています。

3.追加質問
intRet = objWin32_Process.Create(strVBS, Null, Null, intProcessID)のintRetの戻り値で、実行したvbsファイルのプログラミングで戻り値を指定して受け取ることはできないのでしょうか?
もし、それを実現したいとしたら、batファイルを使ってvbsファイルからの戻り値を%errorlevel%で受け取るなどしなければならないのでしょうか?

以下がソースですが、細かいところのミスなども指摘いただけると助かります。

すみませんがよろしくお願いします。
-----------------------------------
strComputer = "リモートのPC名"
strUser = "Administrator"
strPassword = "パスワード"
strVBS = "cscript C:\tmp\~.vbs"

' リモートに接続
Set objWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objwbemLocator.ConnectServer _
(strComputer, "root\cimv2", strUser, strPassword)

objWMIService.Security_.authenticationLevel = 6
objWMIService.Security_.impersonationLevel = 3

' Win32_Process クラスを生成
Set objWin32_Process = objWMIService.Get("Win32_Process")


intRet = objWin32_Process.Create(strVBS, Null, Null, intProcessID)

Set objWbemLocator = Nothing
Set objWMIService = Nothing

補足日時:2009/12/01 13:39
    • good
    • 0

部下に WMI を研修するために、自身で勉強しながら資料を作ってる最中なもので、的外れかもしれません。



サービスを停止するだけなら、サーバーA にある VBS で、サーバーB の Win32_Service にアクセスして、StopService() メソッドで Apache のサービスを停止するってのはどうでしょうか?
Apache のサービスが Windows のサービスなのかどうかよくわかりませんが。

または、現在のサーバーA 側のスクリプトは、サーバーB の Win32_Process にアクセスして CScript.exe を起動させてますが、
サーバーA 側のスクリプトで WScript の WshController オブジェクトを使って、サーバーA 側のスクリプトを直接サーバーB に実行してもらうって手もあるかもしれません。
http://www.atmarkit.co.jp/fwin2k/operation/wsh09 …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

初めは、WshController オブジェクトを使ってリモート実行を考えていたのですが、WshController オブジェクトを使う前提としてレジストリを変更しなければならず、サーバ管理者からそれは絶対NGといわれたので、その方法はとれませんでした。
 リモートvbsの実行を受け付けます、という設定に変えることになるので、セキュリティ的に問題があるからです。

上段のWin32_Service にアクセスでやってみたら、あっさりリモートでApacheの停止ができました。
時間のない中でじっくり勉強できずに次々作ってしまっている弊害なのか、気づきませんでした。ありがとうございます。

以下、スクリプトです。
--------------------------------------
Dim strQuery ' サービス取得SQL
Dim strServiceName ' サービス名
Dim lngServiceCount ' サービス数
Dim objServiceList ' 対象の サービス一覧
Dim objServiceInfo ' サービスの情報
Dim lngRetCode ' 戻り値
Dim strComputer ' PC


strServiceName = "Apache2.2"
strComputer = "PC名"
lngServiceCount = 0


strQuery = "SELECT * FROM Win32_Service WHERE Name = '" & strServiceName & "'" 'サービス取得SQL

Set objServiceList = GetObject("winmgmts:\\" & strComputer & "\root\cimv2").ExecQuery(strQuery)


For Each objServiceInfo In objServiceList

lngRetCode = objServiceInfo.StopService() 'サービスの停止

lngServiceCount = lngServiceCount + 1
Next

'メモリ解放
Set objServiceList = Nothing
Set objServiceInfo = Nothing

今は、リモートで共有フォルダを作ってデータコピーした後に共有を解除するという課題に取り組んでおります。
リモートで、コマンドプロンプトを実行する例の方法が使えそうです。

http://www.microsoft.com/japan/technet/scriptcen …

お礼日時:2009/12/04 15:10

> batファイルを使ってvbsファイルからの戻り値を%errorlevel%で受け取るなどしなければならないのでしょうか?



気になったので実験してみました。
1."cscript 存在しない.vbs" を実行する
Win32_Process.Create のリターンコードは 9、bat で得たリターンコードは 1 でした。
2."cscript C:\tmp\test.vbs" を実行する
test.vbs の中身は WScript.Quit(100) の1行のみです。
Win32_Process.Create のリターンコードは 0、bat で得たリターンコードは 100 でした。
つまり、Create メソッドが独自に生成したリターンコードを返すようです。

代替案1.サーバー側の実行スクリプトで実行結果をファイルに書き出す
 共有フォルダなどに書き込んでそれを確認する。
 ファイル名で実行結果が分かるようにしたらいかがでしょうか。

代替案2.WshRemote を使い、リモート用のスクリプトで Err.Raise を発生させてそれを受け取る
 bat ファイルで %errorlevel% を受け取ってそれをさらに処理するのとあまり変わりませんね。

とりあえず、コードのダイエットを。
ユーザー名とパスワードは記述する必要が無くなります。
----------------
strComputer = "リモートのPC名"
strVBS = "cscript C:\tmp\~.vbs"

' リモートに接続
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

' Win32_Process クラスを生成
Set objWin32_Process = objWMIService.Get("Win32_Process")

intRet = objWin32_Process.Create(strVBS, Null, Null, intProcessID)

Set objWMIService = Nothing

この回答への補足

おかげでコードのダイエットができました。
ありがとうございます。

代替案1.を検討したのですが、
結果のファイルが残っていくため削除処理をしなければならないのが面倒なので他を検討するよう言われたので、リモートでイベントログを取得して、管理側サーバで各サーバのVBScriptの実行を管理することにしました。

前提としてVBScriptの中で、イベントログの特定のエントリに結果などを出力しておくことが必要ですが。
リモートでイベントログを取得、はWMIにもともと備わってるので
簡単にできました。

補足日時:2009/12/04 13:41
    • good
    • 0
この回答へのお礼

忙しいところ、ありがとうございます。

お礼日時:2009/12/04 14:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!