LoginSignup
6
8

More than 5 years have passed since last update.

Windowsサーバー上のTomcatにデプロイするbatファイルを作ってみた

Last updated at Posted at 2015-06-22

はじめに

今のPJでは開発サーバー(Windows Server 2008 R2)は社内環境上に、Jenkinsは別の環境上にあるという状況のため開発サーバーにあるTomcatにデプロイするために、
1. 自分のローカルマシンにインターネットでJenkinsに繋いで、ビルドしたwarをダウンロード
2. 自分のローカルマシンから開発サーバーにリモートデスクトップで繋いで、warをデプロイ
ということを手作業で行っています。
※開発サーバーはインターネットに繋いじゃダメという前提です。

env.png

1回、2回の作業なら別にいいんですが、毎日となると面倒臭くてしょうがなかったため、batファイルを使って一発でデプロイできるものを作ってみました。

Windows用のwgetとPsToolsのインストール

今回作ったbatファイルでは、Jenkinsからwarをダウンロードするのにwgetコマンドを、Tomcatのworkディレクトリを削除したりするのにPsToolsのpsexecコマンドを使っています。
wgetはLinuxに入っているのとまったく同じように使えるものなので、説明は割愛します。
psexecはリモートマシン上にあるコマンドを実行することができるコマンドです。

というわけで、まずwgetとpsexecが使えるようにします。

wgetをインストール

  1. http://gnuwin32.sourceforge.net/packages/wget.htm からBinariesとDependenciesのzipをローカルに保存
  2. 保存したzipを両方解凍してDependencies側のbinフォルダ配下の全てのdllをBinaries側のbinフォルダにコピー
  3. Binaries側のbinにPathを通す

PsToolsのインストール

  1. https://technet.microsoft.com/ja-jp/sysinternals/bb896649.aspx からPsToolsをダウンロード
  2. ダウンロードしたzipを解凍して、Pathを通す

デプロイするbatファイル

作ったbatファイルは以下の様な感じです。

deploy.bat

@echo off

rem ***************************************
rem ログファイル名取得
rem ***************************************
echo %date%
echo %time%

set yyyy=%date:~0,4%
set mm=%date:~5,2%
set dd=%date:~8,2%

set time2=%time: =0%

set hh=%time2:~0,2%
set mn=%time2:~3,2%
set ss=%time2:~6,2%

set filename=%yyyy%-%mm%%dd%-%hh%%mn%%ss%

set log=%filename%.log

rem **********************************************************
rem Jenkinsからwarを取得
rem **********************************************************
wget -N -P "C:\for_remote_deploy_temp"  http://<jenkins_host>/jenkins/job/<target_job>/lastSuccessfulBuild/artifact/dist/target.war >> %log% 2>&1
if %ERRORLEVEL% neq 0 goto error

rem **********************************************************
rem APサーバーのTomcatを停止する
rem **********************************************************
for /F "tokens=1,2,3,4,5 usebackq delims= " %%a in (`sc <deploy_server_host> query "Tomcat6" ^| findstr -i state`) do ( 
  if "%%a"=="STATE" ( 
      if "%%d"=="RUNNING" ( 
           sc <deploy_server_host> stop "Tomcat6"  >> %log% 2>&1
           if %ERRORLEVEL% neq 0 goto error
      ) 
   ) 
 ) 
rem **********************************************************
rem サーバーが止まっているか確認して、止まっていなかったら30秒待つ
rem **********************************************************
set /a CNT=0

:wait_for_stopping
for /F "tokens=1,2,3,4,5 usebackq delims= " %%a in (`sc <deploy_server_host> query "Tomcat6" ^| findstr -i state`) do (
    if "%%a"=="STATE" ( 
        if "%%d" neq "STOPPED" ( 
            timeout 30 
        ) else ( 
            goto continue_process 
        ) 
    ) 
 ) 
set /A CNT=%CNT%+1

if "%CNT%" lss "2" ( 
  goto wait_for_stopping 

 ) else ( 
  goto exit 
 )


:continue_process
rem ******************************************************************
rem psexecコマンドを使用して、warと展開ディレクトリ、workを全削除する
rem ******************************************************************
rem war削除
psexec <deploy_server_host> cmd /c del <tomcat_catalina_base>\webapps\target.war  >> %log% 2>&1
if %ERRORLEVEL% neq 0 goto error

rem 展開ディレクトリ削除
psexec <deploy_server_host> cmd /c rd <tomcat_catalina_base>\webapps\target /s /q  >> %log% 2>&1
if %ERRORLEVEL% neq 0 goto error

rem work削除
psexec <deploy_server_host> cmd /c rd <tomcat_catalina_base>\work\target /s /q  >> %log% 2>&1
if %ERRORLEVEL% neq 0 goto error

rem **********************************************************
rem xcopyでwarをAPサーバーにコピーする
rem **********************************************************
xcopy "C:\for_remote_deploy_temp\target.war" "<tomcat_catalina_base>\webapps"  >> %log% 2>&1
if %ERRORLEVEL% neq 0 goto error

rem **********************************************************
rem APサーバーのTomcatを開始する
rem **********************************************************
sc <deploy_server_host> start "Tomcat6"  >> %log% 2>&1
if %ERRORLEVEL% neq 0 goto error

:error

:exit
exit

適当な解説

scコマンド

サービス管理/操作するためのコマンドです。ホストを指定してあげるとリモートマシンにも使うことができます。対象のサービスは、タスクマネージャのサービスタブに表示されるサービス表示名ではなく、内部KEY名で指定する必要があります。
TomcatをWindowsにデフォルトインストールした場合は、

  • 内部KEY名:Tomcat6
  • サービス表示名:Apache Tomcat 6

となっています。
サービス表示名から内部KEY名を引くためには

GetKeyName.bat
C:\>sc <host> GetKeyName "Apache Tomcat 6"
[SC] GetServiceKeyName SUCCESS
名前 = Tomcat6

とするとわかります。

scコマンドでサービスの起動/停止をすると、起動/停止のシグナルは送信しますが実際にサービスが動き始めたのか、止まったのかまではわかりません。(シグナルを送信した時点でコマンドが返ってきてしまうため)

現時点でのサービスの状態を知るためには、下記のようにqueryを使います。

statusCheck.bat
C:\>sc <host> query "Tomcat6"
SERVICE_NAME: Tomcat6
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

今回作ったbatファイルではfor文のtokens,usebackq,delimsを使い、STATE部分の文字列を抜き出し、取得したサービスの状態によって次処理を切り替えるようにしています。

もしコピって使いたいという方がいたら・・・

自分が作っていて、ハマったポイントがあるので書いておきます。コピって使う方がいたら注意して下さい。(batファイル作る上で常識っぽい事なので、知っている方は読み飛ばして下さい。)

  1. if文の括弧 "(" と ")"の前後には、”必ず”空白を入れて下さい。
    空白がデリミタになっているようなので、空白がないと正しく動きません。

  2. for文でusebackqを指定しinでコマンドを発行する場合、パイプでコマンドをつなぐことが可能ですが、パイプの前にキャレット"^"でエスケープする必要があります。

  3. for文で半角スペースをデリミタにして文字列を分割するためdelimsを指定しています。なので、delimsの直後には半角スペースが入っています。

psserviceコマンドについて

今回作ったbatファイルでは、Tomcatサービスの起動/停止にscコマンドを使っていますが、PsToolsにもリモートマシンのサービスを管理/操作するpsserviceというコマンドがあります。最初はpsserviceを使っていたのですがバグ?があるようで、psserviceでサービスを操作するとリモートマシンのCPUが100%に張り付いてしまうため、使用を断念しました。

追記(2015/06/25更新)

scコマンドのqueryexについて

上のscコマンドのqueryよりさらに詳細情報を取得できるqueryexというのがあります。

queryex.bat
c:\>sc <host> queryex "Tomcat6"

SERVICE_NAME: Tomcat6
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
        PID                : 8872
        FLAGS              :

これを使うとPIDも取得できます。
例えば、サービスがハングアップしてしまっている状態(STOP_PENDINGなど)で強制的にプロセスをkillしたい場合は、以下のようにするといいかもしれません。

taskkill.bat
for /F "tokens=1,2,3,4,5 usebackq delims= " %%a in (`sc <host> queryex "Tomcat6" ^| findstr -i PID`) do ( 
        psexec <host> cmd /c taskkill /PID "%%c" /F >> %log% 2>&1 
        if %ERRORLEVEL% neq 0 goto error 
 ) 

まぁサービスの状態だけで、いきなりプロセスをkillしていいのかっていう話はありますが・・・
ご参考までに

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8