2012年2月1日水曜日

windowsサーバでビルドスクリプトを実行(σ・∀・)σ!!

ポチポチポチ...
パラパラパラパラパラパラパラ( ´ー`)ノシ
( ・`ω・´)<これは何の音ですか??
作業手順書の中から今やる作業を見つけてる音ですヽ(´ー`)ノ

ポチポチポチポチポチポチポチ(σ ´ー`)σ
( ・`ω・´)<これは何の音ですか??
GUI使って、テーブルを作成してる音ですヽ(´ー`)ノ

ブーブーブー( ´ー`)ノ
( ・`ω・´)<これは何の音ですか??
手順どおり更新したのに、なんでかエラーが出ている音ですヽ(´ー`)ノ

(´・ω・`)...

GUIで楽してみても
windowsサーバのシステムを作っていると、
GUIが優れてるんで、ぽちぽちした方が簡単だよ? >ヽ(´ー`)ノ

( ・`д・´)<でもほら、本番で作業がもれてエラーでてるじゃない!!

もうダメ!!ビルドスクリプト作ってそれで構築してっ!

ええー(´Д`)ノ

( ・`д・´)<
【開発環境】⇒【テスト環境】⇒【仮本番環境】⇒【本番環境】
と、そのスクリプトを何度も実行することで、
信頼性がアップしますっ。
どんな作業したのかも、簡単にのこせますし。


実際こんな流れでビルドスクリプトを提案。
Javaでant使ってた身としてはいささか手作業は不思議でした。

windowsでのビルドスクリプトって
選択肢としては、
(1)コマンドプロンプト
(2)VBScript
(3)PowerShell
があります。
非力ではありますが、どこでも使えて簡単に実行できる、
コマンドプロンプトで『build.bat』みたいなのを書いて、
サーバで実行していました。
今回はそのお話。

マシンの種類でビルドスクリプトは分けていて
DBサーバとWebサーバは違うマシンだったので、
それぞれで実行(σ・∀・)σ!
DBサーバでやったのは、
テーブルの作成
列の追加
ビューの作成
テーブルのバックアップ
データの挿入

とかでしたけども、
だいたいはSQLを動かすだけ。
つまりはコマンドプロンプトから任意のSQLが実行できれば、
ビルドスクリプトとしては十分でした。

Webサーバでやったのは、
ディレクトリの作成
権限の付与
ファイルのコピー

とかですね。
こんな感じの
こんな感じのディレクトリ構成で、
sql:実行するSQLファイルがある場所
backup:スクリプト実行前にとったバックアップを保存しておく場所
log:実行結果のログファイルを残す場所
insert:新たにDBのテーブルに追加するデータが入っている場所
DBサーバのビルドスクリプトの例として
それぞれの例はこちらっ↓↓
set dbserver=SERVER
set dbuser=USER
set dbpass=PASS

echo build start ---------------------------------  >> ./log/build.log
echo build実行  >> ./log/build.log
echo %time% %date%  >> ./log/build.log

rem -- table1テーブルのバックアップ
bcp "select * from db1.schema1.table1 where type='A'" queryout  ../backup/table1.bak -n -T -S %dbserver% -U %dbuser% -P %dbpass% >> build.log

rem -- テーブルを作成するSQL実行
sqlcmd  -U %dbuser% -P %dbpass% -i ./sql/createTable.sql -o ./log/result_createTable.log
rem -- データを追加するSQL実行
sqlcmd  -U %dbuser% -P %dbpass% -i ./sql/insertID.sql -o ./log/result_insertID.log
rem -- テーブルに列を追加するSQL実行
sqlcmd  -U %dbuser% -P %dbpass% -i ./sql/addColumn.sql -o ./log/result_addColumn.log

rem ------- table2テーブルにデータを追加
bcp db1.schema1.table2 in ./insert/table2.bak  -n -T -S %dbserver% -U %dbuser% -P %dbpass% >> build.log
echo table2テーブルにデータを追加 >> ./log/build.log

echo %time% %date%  >> ./log/build.log
echo build end  ---------------------------------   >> ./log/build.log
もっと実際は複雑ですが、骨組みだけを取り出せばこんな感じ。
set dbserver=SERVER
こんな感じで使いまわすところは変数に格納します。
いつ、どれくらいで実行したのかを記憶しておくために
echo %time% %date% >> ./log/build.log
で時間をログに出力。
たとえば実行されるSQLとは
たとえば実行するSQLファイルはこんなことが書かれていたりします。

テーブル作成
-- table_one
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'table_one') AND type in (N'U'))
BEGIN
CREATE TABLE table_one(
    one_id      nvarchar (20)  NOT NULL
  , one_name    nvarchar (100) NOT NULL
  , created_on  datetime
  
  ,  CONSTRAINT [PK_table_one] primary key clustered
 (
  one_id ASC
 )
)
END
GO

-- table_two
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'table_two') AND type in (N'U'))
BEGIN
CREATE TABLE table_two(
    two_id      nvarchar (20)  NOT NULL
  , two_name    nvarchar (100) NOT NULL
  , created_on  datetime
  
  ,  CONSTRAINT [PK_table_two] primary key clustered
 (
  two_id ASC
 )
)
END
GO
これでテーブルがひとつ増えて、実行するSQLが追加されても、同じファイルを実行できます。

もしくは、不具合対応のための
while (
          ( select count(*) from db_one.schema_one.users
            where user_id is null
            and   user_name is not null 
          ) > 0
      ) 
begin

    update db_one.schema_one.users
    set user_id = (
                             select 'US' + right('000000' + cast(key_number + 1 as nvarchar),6) 
                             from db_one.schema_one.key_table
                             where key_type = 'user_id' 
                        )
    where row_no = 
    (
        select max(row_no) from db_one.schema_one.users
        where user_id is null
        and   user_name is not null
    )

    update db_one.schema_one.key_table
    set key_number = key_number + 1
    where key_type = 'user_id'

end

--『user_id』がnullで『user_name』が書きこまれていることがイレギュラーなこととして。
こんなだったり。

DBのデータを入れたり、出したりは、bcpコマンドを使います。
マシンにもよるかと思いますが、数百万行のデータでも余裕で実行できました。

SQLの実行は、sqlcmdでSQLファイルのあるパスを指定。
どこに何があるのか管理しやすくするため、ファイルは分けてあります。
Webサーバでのビルドスクリプト
set hname=WEBSERVER

echo build start ---------------------------------  >> ./build/build.log
echo directory作成  >> ./build/build.log
echo %time% %date%  >> ./build/build.log

rem ------- tmp作成
if not exist D:\dev\tmp     mkdir D:\dev\tmp >> ./build/build.log
echo y|cacls D:\dev\tmp /E /G iusr_%hname%:c >> ./build/build.log
echo tmp OK >> ./build/build.log

rem ------- img作成
if not exist D:\dev\img     mkdir D:\dev\img >> ./build/build.log
echo y|cacls D:\dev\img     /E /G iusr_%hname%:c >> ./build/build.log
echo img OK >> ./build/build.log

echo build end  ---------------------------------   >> ./build/build.log
作成するディレクトリがなければ、作成します。
if not exist D:\dev\tmp mkdir D:\dev\tmp
あとは権限を付与。
iuserはマシン名を持つことが多いので、「iusr_%hname%」としています。
cacls D:\dev\tmp /E /G iusr_%hname%:c
これだと確認を求められるので、
パイプで「y」を送っておいて、その作業を代行します。
echo y|cacls D:\dev\tmp /E /G iusr_%hname%:c

まあだいたいはこんな感じですね。

これよりもっと複雑になってくると、
普通にVBScriptを書いて実行した方が現実的です。

0 件のコメント:

コメントを投稿