maven central に存在しない 3rd party 製 jar の扱い方

概要

ビルドシステムとして maven を使用している場合に、maven central に存在しない 3rd party 製 jar を扱う方法をいくつか考察してみました。

  1. 3rd party に頼んで jar を central repository にアップしてもらう
  2. 社内リポジトリに jar を deploy する
  3. ローカルリポジトリに jar を install する
  4. system scope で扱う
  5. localRepositoryPath を使用する
  6. localRepositoryPath と maven-shade-plugin を併用する

各方法の考察

3rd party に頼んで jar を central repository にアップしてもらう

これが最初に考慮すべき方法で、最も理想的な方法です。

しかし、時間的余裕が無い場合やNDAを前提としてjarが配布される場合などは、選択肢に含まれないかもしれません。

社内リポジトリに jar を deploy する

開発環境が社内に閉じている場合は、この方法がセカンドベストです。アクセス制限なども可能となるので、NDAを前提としてjarが配布される場合などにも対応が可能です。

しかし、開発環境が社内に閉じていない場合には何らかの対策が必要になります。

ローカルリポジトリに jar を install する

各自が何らかの方法で jar を取得してローカルリポジトリに install する方法は、さまざまな開発環境に柔軟に対応できます。

しかし、独自に jar を取得する手間と、その jar をローカルリポジトリに install する手間がかかります。また、VCS からチェックアウトした直後にコンパイルが通らないためバグと勘違いされて無用な工数をかけてしまう可能性もあります。

例:

mvn install:install-file -Dfile=[your jar file] -DgroupId=[groupId] -DartifactId=[artifactId] -Dversion=[version] -Dpackaging=jar

参考:http://maven.apache.org/plugins/maven-install-plugin/install-file-mojo.html

system scope で扱う

packaging が war や apk のように、ライブラリとして外部参照されるものでない場合はには優れた方法です。jar をプロジェクト内部に入れておけば、VCS からチェックアウトした状態でコンパイルを通すことができます。

しかし、packaging が jar の場合など、ライブラリとして外部から参照される場合には、参照する側が 3rd party の jar を取得できないという問題があります。*1

参考:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#System_Dependencies

localRepositoryPath を使用する

system scope で扱う場合に似た特徴を持ちますが、install する手間がかかります。

対象の jar をプロジェクト内リポジトリに install する例

プロジェクト内の repo ディレクトリ以下に 3rd party 製の jar を install して VCS 上にコミット:

project.basedir からコマンドラインで install する場合:

mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...]

ビルドシステムがプロジェクト内レポジトリを参照する場合の pom.xml設定例:

  <!-- Repositories : http://maven.apache.org/pom.html#Repositories -->
  <repositories>
    <repository>
      <id>repo</id>
      <releases>
        <enabled>true</enabled>
        <checksumPolicy>ignore</checksumPolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <url>file://${project.basedir}/repo</url>
    </repository>
  </repositories>

※マルチプロジェクトの場合は root の pom.xml だけに記述すればOKです

localRepositoryPath と maven-shade-plugin を併用する

packaging が jar の場合など、ライブラリとして外部から参照される場合にも対応可能な方法です。3rd party の jar の内容を自身の jar に含めてしまうため、このプロジェクトを参照する側に一切の仕掛けは必要ありません。

localRepositoryPath を使用する方法を採用し、さらに以下のように対象ライブラリを指定して、成果物の jar に含めてしまいます。

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <artifactSet>
            <includes>
              <include>[target_lib_group]:[target_lib_artifact]</include>
            </includes>
          </artifactSet>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

この方法は、system scope では実現できないので、注意してください。*2

まとめ

ケースバイケースですね。

*1:たとえば、3rd party ライブラリが a.jar に含まれ、b.apk が a.jar を参照するが 3rd party ライブラリを直接参照していない場合、コンパイル時には問題を検出できず、実行時にいきなり NoClassDefFoundError 等で落ちます。

*2:system scope はあらゆるシステムに存在することが前提と考えられるため、maven-shade-plugin の対象にはなりません

linux-x64用MySQLのインストール

参考情報

今回の対象は mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz になります。

mysqlユーザーとグループの作成

groupadd mysql
useradd -r -g mysql mysql

設定ファイルの配置

/etc/my.cnf を配置する。以下例。

# Example MySQL config file for medium systems.
#
# This is for a system with little memory (32M - 64M) where MySQL plays
# an important part, or systems up to 128M where MySQL is used together with
# other programs (such as a web server)
#
# MySQL programs look for option files in a set of
# locations which depend on the deployment platform.
# You can copy this option file to one of those
# locations. For information about these locations, see:
# http://dev.mysql.com/doc/mysql/en/option-files.html
#
# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
# with the "--help" option.

# The following options will be passed to all MySQL clients
[client]
#password	= your_password
port		= 3306
socket		= /tmp/mysql.sock

# Here follows entries for some specific programs

# The MySQL server
[mysqld]
basedir = /opt/mysql/mysql
port		= 3306
socket		= /tmp/mysql.sock
skip-external-locking
key_buffer_size = 64M
max_allowed_packet = 1M
table_open_cache = 256
sort_buffer_size = 4M
net_buffer_length = 8K
read_buffer_size = 1M
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M

character-set-server = utf8mb4
skip-character-set-client-handshake
default-storage-engine = InnoDB

slow_query_log  = 1
slow_query_log_file = slow_query.log
long_query_time = 0.5
log-queries-not-using-indexes = 1

general-log = 1
general_log_file = query.log

# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (via the "enable-named-pipe" option) will render mysqld useless!
# 
#skip-networking

# Replication Master Server (default)
# binary logging is required for replication
#log-bin=mysql-bin

# binary logging format - mixed recommended
#binlog_format=mixed

# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
# but will not function as a master if omitted
server-id	= 1

# Replication Slave (comment out master section to use this)
#
# To configure this host as a replication slave, you can choose between
# two methods :
#
# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
#    the syntax is:
#
#    CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
#    MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
#
#    where you replace <host>, <user>, <password> by quoted strings and
#    <port> by the master's port number (3306 by default).
#
#    Example:
#
#    CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
#    MASTER_USER='joe', MASTER_PASSWORD='secret';
#
# OR
#
# 2) Set the variables below. However, in case you choose this method, then
#    start replication for the first time (even unsuccessfully, for example
#    if you mistyped the password in master-password and the slave fails to
#    connect), the slave will create a master.info file, and any later
#    change in this file to the variables' values below will be ignored and
#    overridden by the content of the master.info file, unless you shutdown
#    the slave server, delete master.info and restart the slaver server.
#    For that reason, you may want to leave the lines below untouched
#    (commented) and instead use CHANGE MASTER TO (see above)
#
# required unique id between 2 and 2^32 - 1
# (and different from the master)
# defaults to 2 if master-host is set
# but will not function as a slave if omitted
#server-id       = 2
#
# The replication master for this slave - required
#master-host     =   <hostname>
#
# The username the slave will use for authentication when connecting
# to the master - required
#master-user     =   <username>
#
# The password the slave will authenticate with when connecting to
# the master - required
#master-password =   <password>
#
# The port the master is listening on.
# optional - defaults to 3306
#master-port     =  <port>
#
# binary logging - not required for slaves, but recommended
#log-bin=mysql-bin

# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = ibdata
innodb_data_file_path = ibdata1:1G
#innodb_log_group_home_dir = ibdata
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 128M
innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size = 32M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50

innodb_file_per_table
innodb_file_format=barracuda
innodb_strict_mode=1

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates

[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

/etc/my.cnf のファイルパーミッションの設定

chown root:mysql /etc/my.cnf
chmod 660 /etc/my.cnf

インストール

# 作業ディレクトリの作成
mkdir /tmp/mysql-installation-working-dir
cd /tmp/mysql-installation-working-dir

# 環境変数の設定
VERSION="5.6.12"

# MySQLのダウンロード
wget -O mysql-${VERSION}-linux-glibc2.5-x86_64.tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-${VERSION}-linux-glibc2.5-x86_64.tar.gz/from/http://cdn.mysql.com/

# shared library のインストール
yes | apt-get install libaio1

# MySQLのインストール
mkdir -p /opt/mysql
cd /opt/mysql
tar zxvf /tmp/mysql-installation-working-dir/mysql-${VERSION}-linux-glibc2.5-x86_64.tar.gz
ln -s mysql-${VERSION}-linux-glibc2.5-x86_64 mysql
cd mysql
chown -R mysql:mysql /opt/mysql
scripts/mysql_install_db --user=mysql
chown -R root .
chown -R mysql data
cp support-files/mysql.server /etc/init.d/mysql

# /usr/local/bin にリンクしておく
ln -f -s /opt/mysql/mysql/bin/innochecksum /usr/local/bin/innochecksum
ln -f -s /opt/mysql/mysql/bin/myisampack /usr/local/bin/myisampack
ln -f -s /opt/mysql/mysql/bin/mysqladmin /usr/local/bin/mysqladmin
ln -f -s /opt/mysql/mysql/bin/mysql_client_test_embedded /usr/local/bin/mysql_client_test_embedded
ln -f -s /opt/mysql/mysql/bin/mysqld-debug /usr/local/bin/mysqld-debug
ln -f -s /opt/mysql/mysql/bin/mysql_embedded /usr/local/bin/mysql_embedded
ln -f -s /opt/mysql/mysql/bin/mysql_plugin /usr/local/bin/mysql_plugin
ln -f -s /opt/mysql/mysql/bin/mysqltest /usr/local/bin/mysqltest
ln -f -s /opt/mysql/mysql/bin/mysql_zap /usr/local/bin/mysql_zap
ln -f -s /opt/mysql/mysql/bin/msql2mysql /usr/local/bin/msql2mysql
ln -f -s /opt/mysql/mysql/bin/my_print_defaults /usr/local/bin/my_print_defaults
ln -f -s /opt/mysql/mysql/bin/mysqlbinlog /usr/local/bin/mysqlbinlog
ln -f -s /opt/mysql/mysql/bin/mysql_config /usr/local/bin/mysql_config
ln -f -s /opt/mysql/mysql/bin/mysqld_multi /usr/local/bin/mysqld_multi
ln -f -s /opt/mysql/mysql/bin/mysql_find_rows /usr/local/bin/mysql_find_rows
ln -f -s /opt/mysql/mysql/bin/mysql_secure_installation /usr/local/bin/mysql_secure_installation
ln -f -s /opt/mysql/mysql/bin/mysqltest_embedded /usr/local/bin/mysqltest_embedded
ln -f -s /opt/mysql/mysql/bin/perror /usr/local/bin/perror
ln -f -s /opt/mysql/mysql/bin/myisamchk /usr/local/bin/myisamchk
ln -f -s /opt/mysql/mysql/bin/mysql /usr/local/bin/mysql
ln -f -s /opt/mysql/mysql/bin/mysqlbug /usr/local/bin/mysqlbug
ln -f -s /opt/mysql/mysql/bin/mysql_config_editor /usr/local/bin/mysql_config_editor
ln -f -s /opt/mysql/mysql/bin/mysqld_safe /usr/local/bin/mysqld_safe
ln -f -s /opt/mysql/mysql/bin/mysql_fix_extensions /usr/local/bin/mysql_fix_extensions
ln -f -s /opt/mysql/mysql/bin/mysql_setpermission /usr/local/bin/mysql_setpermission
ln -f -s /opt/mysql/mysql/bin/mysql_tzinfo_to_sql /usr/local/bin/mysql_tzinfo_to_sql
ln -f -s /opt/mysql/mysql/bin/replace /usr/local/bin/replace
ln -f -s /opt/mysql/mysql/bin/myisam_ftdump /usr/local/bin/myisam_ftdump
ln -f -s /opt/mysql/mysql/bin/mysqlaccess /usr/local/bin/mysqlaccess
ln -f -s /opt/mysql/mysql/bin/mysqlcheck /usr/local/bin/mysqlcheck
ln -f -s /opt/mysql/mysql/bin/mysql_convert_table_format /usr/local/bin/mysql_convert_table_format
ln -f -s /opt/mysql/mysql/bin/mysqldump /usr/local/bin/mysqldump
ln -f -s /opt/mysql/mysql/bin/mysqlhotcopy /usr/local/bin/mysqlhotcopy
ln -f -s /opt/mysql/mysql/bin/mysqlshow /usr/local/bin/mysqlshow
ln -f -s /opt/mysql/mysql/bin/mysql_upgrade /usr/local/bin/mysql_upgrade
ln -f -s /opt/mysql/mysql/bin/resolveip /usr/local/bin/resolveip
ln -f -s /opt/mysql/mysql/bin/myisamlog /usr/local/bin/myisamlog
ln -f -s /opt/mysql/mysql/bin/mysqlaccess.conf /usr/local/bin/mysqlaccess.conf
ln -f -s /opt/mysql/mysql/bin/mysql_client_test /usr/local/bin/mysql_client_test
ln -f -s /opt/mysql/mysql/bin/mysqld /usr/local/bin/mysqld
ln -f -s /opt/mysql/mysql/bin/mysqldumpslow /usr/local/bin/mysqldumpslow
ln -f -s /opt/mysql/mysql/bin/mysqlimport /usr/local/bin/mysqlimport
ln -f -s /opt/mysql/mysql/bin/mysqlslap /usr/local/bin/mysqlslap
ln -f -s /opt/mysql/mysql/bin/mysql_waitpid /usr/local/bin/mysql_waitpid
ln -f -s /opt/mysql/mysql/bin/resolve_stack_dump /usr/local/bin/resolve_stack_dump

設定ファイルの修正

/etc/init.d/mysql に環境情報をセットする。
以下例:

vi /etc/init.d/mysql
:%s/^basedir=$/basedir=\/opt\/mysql\/mysql
:%s/^datadir=$/datadir=\/opt\/mysql\/mysql\/data

mysqldの起動

/etc/init.d/mysql start

MySQLのルートパスワードの設定等

/opt/mysql/mysql/bin/mysql_secure_installation # パスワードを設定し、以降全部Yで対応。

後片付け

rm -rf /tmp/mysql-installation-working-dir

自動起動設定

update-rc.d mysql defaults

linux-x64用Javaのインストール

インストール対象のJavaを確認する

今回は http://download.oracle.com/otn-pub/java/jdk/7u71-b14/jdk-7u71-linux-x64.tar.gz を対象とする。

ダウンロードとインストール

# 作業ディレクトリの作成
mkdir /tmp/java7-installation-working-dir
cd /tmp/java7-installation-working-dir

# jdk-7u71-linux-x64.tar.gz のダウンロード(cookie情報は頻繁に変わる点に注意)
wget --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u71-b14/jdk-7u71-linux-x64.tar.gz"

# インストール
tar zxvf jdk-7u71-linux-x64.tar.gz
mkdir /opt/java
mv jdk1.7.0_71 /opt/java/jdk1.7.0_71
ln -f -s /opt/java/jdk1.7.0_71 /opt/java/jdk1.7

設定

パスの設定を行う。以下例:

echo '
# for java7
JAVA_HOME=/opt/java/jdk1.7
PATH=$HOME/bin:$JAVA_HOME/bin:$PATH
JRE_HOME=/opt/java/jdk1.7/jre
PATH=$HOME/bin:$JRE_HOME/bin:$PATH
export JAVA_HOME
export JRE_HOME
export PATH' >> /etc/profile

動作確認

. /etc/profile
java -version

後片付け

rm -rf /tmp/java7-installation-working-dir

さくらのVPSへのDebianのインストール

概要

  • さくらのVPSDebianをインストールし、最低限の設定を行います。
  • OSは Debian 7.0(Wheezy) を使用します。

レンタル開始

  • http://vps.sakura.ad.jp/ から申し込みます。
  • 『お申込受付完了のお知らせ』と『仮登録完了のお知らせ』のメールが送付されます。
  • 『仮登録完了のお知らせ』メールに基本情報が記述されています。
  • ※外向き25番ポート利用不可、DNS利用不可、転送量制限等の制限事項があるので、しっかりとメールとメール上のリンクからの情報を確認しておきましょう。

OSインストール前の情報確認

OSのインストール

  • VPSコントロールパネルにログイン。
  • 諸情報はコントロールパネル上の情報を利用。
  • VPSコントロールパネルの左側にある「OS再インストール」を選択。
  • OS再インストール画面が表示されたら「カスタムOSインストールへ」を選択。
  • カスタムOSインストール画面が表示されたら、OS選択で「Debian 7 amd64」を選択し、画面下部の「確認」を押下。
  • 確認画面が表示されるので、OSが「Debian 7 amd64」であることを確認してから「実行」を押下。
  • ブラウザに「インストールを開始しました。」と表示されたら、「HTML5モードで開く(推奨)」を選択し、手順を参考にインストールを続ける。
  • インストール途中で聞かれる root 以外の初期ユーザは作業者自身のアカウントを作成し、パスワードは運用ルールに従って適切に設定する。
  • rootのパスワードは運用ルールに従って適切に設定する。

OSの基本設定

仮想マシンの起動

  • VPSホームから、仮想サーバを起動する。

Debian Linuxへのログイン

  • VPSコントロールパネルの「リモートコンソール」を選択し、以下のようにログインする。
user: 作業者のユーザー名
password: 作業者のパスワード

apt の設定

  • su 後に /etc/apt/sources.list の各行に contrib non-free を追加する(コピペは上部のコピペ用アイコンでできる)
deb http://ftp.jp.debian.org/debian wheezy main contrib non-free
deb-src http://ftp.jp.debian.org/debian wheezy main contrib non-free

deb http://security.debian.org/ wheezy/updates main contrib non-free
deb-src http://security.debian.org/ wheezy/updates main contrib non-free

# wheezy-updates, previously known as 'volatile'
deb http://ftp.jp.debian.org/debian wheezy-updates main contrib non-free
deb-src http://ftp.jp.debian.org/debian wheezy-updates main contrib non-free

Debianのアップデート

# resynchronize the package index files from their sources
apt-get update

# install the newest versions of all packages currently installed on the system from the sources
apt-get upgrade

# remove packages that were automatically installed to satisfy dependencies for some package and that are no more needed
apt-get autoremove

# clears out the local repository of retrieved package files
apt-get clean

# updates the package cache and checks for broken dependencies
apt-get check

sshの設定

通常はネットワーク経由で作業を行うため、ssh の設定を行い、以降は ssh 経由で作業を行う。

作業者のSSH認証用設定

作業者全員分の公開鍵を設定する。以下例:

USER_NAME="作業者のユーザー名"
PUB_KEY="作業者の公開鍵"
mkdir /home/$USER_NAME/.ssh
chmod 700 /home/$USER_NAME/.ssh
echo $PUB_KEY > /home/$USER_NAME/.ssh/authorized_keys
chmod 600 /home/$USER_NAME/.ssh/authorized_keys
chown -R $USER_NAME:$USER_NAME /home/$USER_NAME/.ssh
sshdの設定
  • ポート番号を 22 から別の番号に変更(今回は便宜的に56789番ポートとする)
  • ssh接続時のrootログインを禁止
  • パスワード認証を禁止

以下はviで目視確認しながら置換を行う例:

vi /etc/ssh/sshd_config

↓以下はviのコマンド
:%s/Port 22/Port 56789/gc
:%s/PermitRootLogin yes/PermitRootLogin no/gc
:%s/#PasswordAuthentication yes/PasswordAuthentication no/gc
sshdの再起動
/etc/init.d/ssh restart

sshd の再起動後、公開鍵認証でログインできるかを確認する。

iptablesの設定

ここに書かれているのはインストール直後の無防備状態よりはマシ程度の最低限の設定。実際に作業をする際には、環境に合った適切な設定をしてください。(日本語だとこことか参考になりそう)

設定概要
  • www(80)を公開
  • https(443)を公開
  • 56789(独自のsshポート)を公開
  • icmpを公開
設定ファイルの作成

以下を実行して設定ファイルを /etc/network/if-pre-up.d/iptables-setup に作成する。*1

echo '#!/bin/sh

### initialize ###
/sbin/iptables -F # テーブルを初期化
/sbin/iptables -X # チェーンを削除

### policies ###
/sbin/iptables -P INPUT   DROP   # 外部からのパケットは基本的に無視する。
/sbin/iptables -P OUTPUT  ACCEPT # 内部で生成されたパケットは基本的に処理する。
/sbin/iptables -P FORWARD DROP   # パケットのルーティングは基本的に行わない。

### rules ###
/sbin/iptables -A INPUT -p TCP -s 0/0 --dport 80 -j ACCEPT                    # tomcat
/sbin/iptables -A INPUT -p TCP -s 0/0 --dport 443 -j ACCEPT                   # tomcat(ssl)
/sbin/iptables -A INPUT -p TCP -s 0/0 --dport 56789 -j ACCEPT                 # ssh
/sbin/iptables -A INPUT -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT                # icmp
/sbin/iptables -A INPUT -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT               # icmp
/sbin/iptables -A INPUT -p ALL -i lo -s 127.0.0.1 -j ACCEPT                   # ローカルループバックからの入力は許可
/sbin/iptables -A INPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT # セッション確立後のパケット疎通は許可' > /etc/network/if-pre-up.d/iptables-setup
chmod 755 /etc/network/if-pre-up.d/iptables-setup
フィルタリングの手動実行
/etc/network/if-pre-up.d/iptables-setup

ntpの設定

ntpのインストール
yes | apt-get install ntp
設定ファイルの変更

/etc/ntp.conf ファイルの下記の箇所を

server 0.debian.pool.ntp.org iburst
server 1.debian.pool.ntp.org iburst
server 2.debian.pool.ntp.org iburst
server 3.debian.pool.ntp.org iburst

下記の内容に置き換える

server ntp1.jst.mfeed.ad.jp
server ntp2.jst.mfeed.ad.jp
server ntp3.jst.mfeed.ad.jp
ntpdの再起動

/etc/init.d/ntp restart

その他必要なパッケージのインストール

自分が必要と思うパッケージを思うままに入れる。

vim のインストール
yes | apt-get install vim

デフォルトのエディタを vim に変更

update-alternatives --config editor

/usr/bin/vim.basic を選択する。

pbzip2 のインストール
apt-get install pbzip2

ユーザの追加

  • adduser コマンドでユーザーを追加する。対話式で色々聞かれるが、パスワード以外は全て エンターを押下し「Is the information correct? [Y/n]」と聞かれたら「Y」を入力してエンターを押下。
  • 各ユーザーに対して、必要に応じてSSHの公開鍵を設定する。以下例:
USER_NAME="作業者のユーザー名"
PUB_KEY="作業者の公開鍵"
mkdir /home/$USER_NAME/.ssh
chmod 700 /home/$USER_NAME/.ssh
echo $PUB_KEY > /home/$USER_NAME/.ssh/authorized_keys
chmod 600 /home/$USER_NAME/.ssh/authorized_keys
chown -R $USER_NAME:$USER_NAME /home/$USER_NAME/.ssh

IPv6の無効化

※本来は無効化ではなくきちんと設定すべきだが、もし取り急ぎ対応したいということであれば下記のようにIPv6を無効化するという方法もある。

  • ipv6を無効にするようにカーネルパラメータを設定してリブートする
echo net.ipv6.conf.all.disable_ipv6=1 > /etc/sysctl.d/disableipv6.conf
  • リブート後、以下を実行してパラメータが 1 になっていることを確認する。
/sbin/sysctl -a --pattern 'net.ipv6.conf.all.disable'

*1:iptables-save/restore を利用したほうが高速なのだが今回はシンプルさを重視した

MySQLでテーブルとカラムの文字コードを一括変更する

既存のデータベースの文字コードを異なる文字コードに変換した際のメモです。

留意すべき点

CONVERT TO CHARACTER SET を用いれば、比較的容易に DB と DB 内の全テーブルの全カラムの文字コードを変換できます。ただし、いくつか留意すべき点があります。

意図しない型の変換に注意!

CONVERT TO CHARACTER SET を用いた場合、型が自動的に変換されてしまうことがあります。
たとえば、utf-8 から utf8mb4 に変更する場合は、text 型のカラムは自動的に mediamtext に変換されます。

これは、VARCHAR や TEXT 系のカラムの文字コードを変換した際、新しいカラムが元のカラムの文字列を格納できることを保証するために行われるとのこと。

For a column that has a data type of VARCHAR or one of the TEXT types, CONVERT TO CHARACTER SET will change the data type as necessary to ensure that the new column is long enough to store as many characters as the original column.

ただし、CONVERT TO CHARACTER SET は文字コードを変換するための機能なので、latin1 から utf8 への変換など、文字コードとして互換性のないデータは変換できません。そのような場合は、CONVERT TO CHARACTER SET を利用せずに以下のように対応する必要があります。

ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;

詳細は、MySQL :: MySQL 5.5 Reference Manual :: 13.1.7 ALTER TABLE Syntax

To change the table default character set and all character columns (CHAR, VARCHAR, TEXT) to a new character set, use a statement like this:

という書き出しの段落にかかれています。

仕様や実装の移り変わりについては、以下を参照のこと。
MySQL Bugs: #31291: ALTER TABLE CONVERT TO CHARACTER SET does not change some data types

テーブルのキーとなるカラムの最大長が 767 バイトを超える場合

1文字の最大サイズの異なる文字コード同士で変換を行う場合、文字コード変換後にテーブルのキーとなるカラムの最大長が 767 バイトを超える場合には変換ができず、以下のようなエラーが発生します。

Specified key was too long; max key length is 767 bytes

たとえば、utf-8 から utf8mb4 に変更する場合、varchar(255) のカラムがキー指定されていた場合は元のカラムの最大長は 511 bytes (255*2) ですが、変更後は 1020 bytes(255*4) となり、767バイトを超えてエラーになります。このような場合は手動での対応が必要になります(後述)。

手順

shell 変数定義

事前に必要な情報を定義しておきます。

MYSQL_DATA_DIR=                         # MySQLのデータフォルダ
MYSQL_BKUP_DIR=                         # MySQLのデータフォルダのバックアップフォルダ
MYSQL_DB=                               # 対象のデータベース名
MYSQL_USER=                             # 対象データベースのユーザー名
MYSQL_PASS=                             # 対象データベースのパスワード
TABLE_INFO_BEFORE=table_info_before.txt # 変更前の CREATE TABLE 情報
TABLE_INFO_AFTER=table_info_after.txt   # 変更後の CREATE TABLE 情報
CONVERT_SCRIP_FILE=convert_script       # 文字コード変換用スクリプト名

データのバックアップ

  • mysqlを停止する
  • data ディレクトリ以下をコピーしてバックアップ
cp -rp ${MYSQL_DATA_DIR} ${MYSQL_BKUP_DIR}

※復元する場合

rm -rf $MYSQL_DATA_DIR; cp -rp ${MYSQL_BKUP_DIR} ${MYSQL_DATA_DIR}

変換前のデータベースとテーブルの定義情報の保存

文字コードを変換する前のデータベースとテーブルの定義情報を保存しておきます。

mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB -e "show create database $MYSQL_DB" --batch --skip-column-names > $TABLE_INFO_BEFORE
mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB -e "show tables" --batch --skip-column-names | xargs -I{} echo 'show create table `'{}'`;' | mysql -u$MYSQL_DB -p$MYSQL_PASS $MYSQL_DB | sed -e 's/\\n/\
/g' >> $TABLE_INFO_BEFORE

文字コード変換用スクリプトの作成

文字コードの変換を行うためのスクリプトを作成します。

(echo 'alter database `'"$MYSQL_DB"'` default character set utf8mb4;'; mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB -e "show tables" --batch --skip-column-names | xargs -I{} echo 'alter table `'{}'` convert to character set utf8mb4;') > $CONVERT_SCRIP_FILE

文字コード変換用スクリプトの目視確認と修正

キー指定されているカラムの最大長が 767 bytes を超えてしまう場合や、自動変換を行いたくないテーブルがある場合などは、必要に応じて修正を加えます。

vi $CONVERT_SCRIP_FILE

手動で指定する場合は、以下のように、1テーブルは1コマンドで変換を行うと効率的です。
(個別に行うとその回数だけテーブル全体の再作成を繰り返すことになります)

例:

alter table MY_TABLE
  default character set utf8mb4,
  modify `my_column1` char(36) character set utf8mb4 NOT NULL,
  modify `my_column2` varchar(16) character set utf8mb4 NOT NULL;

utf8 を utf8mb4 に変換する際に text 型を mediumtext に変換されたくない場合などで、元の DB 内で mediumtext を利用していないのであれば、CONVERT TO CHARACTER SET を利用して変換した後に、以下のように戻すという手もあります。

alter table MY_TABLE modify `my_column` text;

文字コード変換用スクリプトの実行

文字コードの変換を実行します(ついでに時間も計測しておきます)

time mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB < $CONVERT_SCRIP_FILE

変換後のデータベースとテーブルの定義情報の保存

文字コードを変換した後のデータベースとテーブルの定義情報を保存します。

mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB -e "show create database $MYSQL_DB" --batch --skip-column-names > $TABLE_INFO_AFTER
mysql -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB -e "show tables" --batch --skip-column-names | xargs -I{} echo 'show create table `'{}'`;' | mysql -u$MYSQL_DB -p$MYSQL_PASS $MYSQL_DB | sed -e 's/\\n/\
/g' >> $TABLE_INFO_AFTER

変換前後のテーブル定義情報の比較

変換前後のテーブル定義情報を比較し、意図した変換が実行されたかどうかを確認します。

diff $TABLE_INFO_BEFORE $TABLE_INFO_AFTER

my.cnfの設定変更

必要があれば、/etc/my.cnf の設定を変更する

[mysqld]
character-set-server = utf8mb4

以上

雑多メモ

utf8 のカラムに utf8mb4 の文字で where をかけた場合のエラー (select * from MY_TABLE where my_string = ? など)
Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation '='
utf8 のカラムに utf8mb4 の文字を格納しようとした場合のエラー(update MY_TABLE set my_string = ? where id = ? など)
Incorrect string value: '\xF3\xBE\x80\x80' for column 'name' at row 1; nested exception is java.sql.SQLException: Incorrect string value: '\xF3\xBE\x80\x80' for column 'name' at row 1

gmaven-pluginの日本語設定

私の手元で軽く動かした限りでは sourceEncoding の設定がうまく効かないようです。

JIRAのステータスを見る限りは sourceEndoding 指定はバグ登録されていて既に fixed。${project.build.sourceEncoding} からの設定も対応されているようなのですが、、、。

ワークアラウンドとしては、環境変数を以下のように設定すればエンコーディングを指定できます。
Windows や shell の環境変数として設定しておけばいいでしょう。

環境変数の設定やプラグインの改変をしないで済む設定法ないかな?情報求む!

環境変数設定例

set MAVEN_OPTS="-Dgroovy.source.encoding=UTF-8"

pom.xml設定例

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.gmaven</groupId>
        <artifactId>gmaven-plugin</artifactId>
        <version>1.5</version>
        <executions>
          <execution>
            <goals>
              <goal>generateStubs</goal>
              <goal>compile</goal>
              <goal>generateTestStubs</goal>
              <goal>testCompile</goal>
            </goals>
            <configuration>
              <providerSelection>1.8</providerSelection>
              <sourceEncoding>UTF-8</sourceEncoding><!-- It doesn't work. -->
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

DebianとTomcat

Debian に Tomcat7 をインストールする。

事前準備

ビルドする必要があるので、事前にビルドに必要なパッケージを導入しておく。

yes | apt-get install build-essential

インストール

# 作業ディレクトリの作成
mkdir /tmp/tomcat-installation-working-dir
cd /tmp/tomcat-installation-working-dir

# 変数定義
VERSION="7.0.42"
JDK_PATH="/opt/java/jdk1.7"
GROUP_ID="10001"
USER_ID="10001"
GROUP="tomcat"
USER="tomcat"

# Tomcat のダウンロード
wget -O apache-tomcat-${VERSION}.tar.gz http://ftp.kddilabs.jp/infosystems/apache/tomcat/tomcat-7/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz

# tomcat group/user の作成
groupadd -g ${GROUP_ID} ${GROUP}
useradd --uid ${USER_ID} --gid ${GROUP_ID} --shell /bin/sh -d /opt/tomcat ${USER}

# tomcat の展開とビルド
tar zxf apache-tomcat-${VERSION}.tar.gz
cd apache-tomcat-${VERSION}/bin
tar zxf commons-daemon-native.tar.gz
cd commons-daemon-1.0.*-native-src/unix
./configure --with-java=${JDK_PATH}
make
chmod 744 jsvc
mv jsvc ../..
cd ../../..
rm -rf bin/commons-daemon-1.0.*-native-src

# opt 配下に展開
mkdir /opt/tomcat
mv /tmp/tomcat-installation-working-dir/apache-tomcat-${VERSION} /opt/tomcat/apache-tomcat-${VERSION}
ln -s /opt/tomcat/apache-tomcat-${VERSION} /opt/tomcat/tomcat
chown -R tomcat:tomcat /opt/tomcat

動作確認

  • /opt/tomcat/tomcat/conf/server.xml ファイル内で 8080 番ポートが指定されている個所について、実際に利用したいポートを指定する。以下は 80 番ポートを利用する例:
vi /opt/tomcat/tomcat/conf/server.xml
:%s/8080/80/cg
/opt/tomcat/tomcat/bin/startup.sh
telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.0

HTTP/1.1 200 OK

レスポンスの先頭行がHTTP/1.1 200 OK が表示されれば正常。

/opt/tomcat/tomcat/bin/shutdown.sh

tomcat manager の権限設定

/opt/tomcat/apache-tomcat-${VERSION}/conf/tomcat-users.xml を以下のように変更する。

<?xml version="1.0" encoding="utf-8"?>
<tomcat-users>
  <user username="admin" password="tomcatadmin" roles="manager-gui,admin-gui"/>
</tomcat-users>
  • 不要な Web Application の削除
rm -rf /opt/tomcat/apache-tomcat-${VERSION}/webapps/docs/
rm -rf /opt/tomcat/apache-tomcat-${VERSION}/webapps/examples/
rm -rf /opt/tomcat/apache-tomcat-${VERSION}/webapps/ROOT/

# 以下は必要なら削除しない
rm -rf /opt/tomcat/apache-tomcat-${VERSION}/webapps/host-manager/

セッション情報の永続化の禁止

  • コンテキストの再起動時にセッション情報を引き継ぎたいという要求が無い場合は永続化を禁止する。デフォルトでは /opt/tomcat/apache-tomcat-${VERSION}/work/Catalina/localhost/コンテキスト名/SESSIONS.ser ファイルにセッション情報が格納されるが、以下の設定を行うとそれが作成されなくなる。

/opt/tomcat/apache-tomcat-7.0/conf/context.xml を編集し、以下の部分をアンコメントする。

<Manager pathname="" />

自動起動設定

  • jsvc による起動をサポートするため、daemon.sh を /etc/init.d/tomcat ファイルを配置
cp /opt/tomcat/apache-tomcat-${VERSION}/bin/daemon.sh /etc/init.d/tomcat
  • service 用の情報を /etc/init.d/tomcat に以下のように追加
# resolve links - $0 may be a softlink

### BEGIN INIT INFO
# Provides: tomcat
# Required-Start: $network $syslog
# Required-Stop: $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: start and stop tomcat
# Short-Description: start and stop tomcat
### END INIT INFO

ARG0="$0"
  • 環境設定ファイルの配置

daemon.sh の内部では、以下の優先度で設定ファイルを読み込みます。

$CATALINA_BASE/bin/setenv.sh
$CATALINA_HOME/bin/setenv.sh

そのため、/opt/tomcat/apache-tomcat-${VERSION}/bin/setenv.sh を作成します。
以下例:

#!/bin/bash

export JAVA_HOME=/opt/java/jdk1.7
export JAVA_OPTS="-server -Xmx256m -Xms256m"
export CATALINA_OPTS=""
  • service に登録
update-rc.d tomcat start 90 2 3 4 5 . stop 10 0 1 6 .

tomcat のインストールと最低限の設定はこんな感じ。設定系は別記します。

後片付け

rm -rf /tmp/tomcat-installation-working-dir