旅するえんじにあ - Engineers to Travel -

旅するエンジニアの気まま備忘録

【PHP】 PHPでの静的解析 SonarQubeを使ってみた

最近ネタもなく、日々テストとLibraryの作成を行っていました。 という言い訳で更新しないのは悪だと思っているので、ちょっと心いれかえて。

今回はPHPの静的解析についてです。 前々から静的解析ツールについては良い物が見当たらず、もちろんあるっちゃあるのですが コレジャナイ感が強かったのですが、勧められたツールがあったのでそれを今回は導入していきたいと思います。

静的解析って?

まずは静的解析とは何か。

静的解析とはプログラムを実行せずに、コードの問題点を見つける。 特定のコーディングパターンに違反している箇所を指摘する。

というのもになります。 少人数で開発していたとしてもレガシーなコードは増えていきます。 コピーして同じロジックが出来上がっていたり、コーディング規約に沿った書き方でない部分 動くけど、これっていいのかな?って思う部分を指摘してくれるわけです。

静的解析ツール

・Scrutinizer

・CodeClimate

・PHPMD

等があるのだが、どうもどれもぱっとしない。 Scrutinizerは使いやすかったけど、なんかいまいち欲しい機能がなかったり、解析速度が遅かったり 1人で使う分にはいいんだけど、実は無料版だと1ヶ月しか解析結果を保持してくれなかったり。

そんな時に見つけたのがSonarQube

対応言語も豊富でユニットテスト連携可(これは他も一緒ですが)、細かく解析が可能な上に、結構WEBが見やすい。 さらにライセンスがLGPLで公開されているので、無料で拡張までできる優れものです。

ということで早速インストールして解析してみました。

ローカル環境

Java jdk jdk-8u45-linux-x64 (jdk1.8.0_45) mysql Ver 14.14 Distrib 5.5.46, for Linux (x86_64) using readline 5.1 sonarqube-5.4 sonar-scanner-2.5

まずはJavaのインストールです。

ソースは基本/usr/local/srcにdownloadするものとします。 wgetにてJDKをダウンロード

cd /usr/local/src

wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.tar.gz"
tar xvf jdk-8u45-linux-x64.tar.gz

解凍したフィアルを移動 /usr/local/javaがない場合は作成

mkdir /usr/local/java
mv /usr/local/src/jdk1.8.0_45 /usr/local/java/

わかりやすいようにシンボリックリンクを張る

ln -s /usr/local/java/jdk1.8.0_45 latest

環境変数JAVA_HOMEを設定する

touch /etc/profile.d/javaenv.sh
touch /etc/profile.d/javaenv.csh
vim /etc/profile.d/javaenv.sh

export JAVA_HOME=/usr/local/java/latest
export PATH=$PATH:$JAVA_HOME/bin
vim /etc/profile.d/javaenv.csh

setenv JAVA_HOME=/usr/local/java/latest
setenv PATH=$PATH:$JAVA_HOME/bin

mysql設定

既にmysqlはインストール済を想定しています ユーザ作成及び権限付与

CREATE USER 'sonar'@'localhost' IDENTIFIED by 'sonar';
GRANT ALL PRIVILEGES ON sonar.* TO 'sonar'@'localhost';

SonarQube用のDatabase作成

CREATE DATABASE sonar;
FLUSH PRIVILEGES;

SonarQubeインストール及び設定

ソースディレクトリに移動してwgetでSonarQubeをダウンロード、解凍

cd /usr/local/src
wget "http://dist.sonar.codehaus.org/sonarqube-5.4.zip"
unzip sonarqube-5.4.zip

解凍したフィアルを移動 移動先ディレクトリは/usr/local/sonarqubeとし、ディレクトリがない場合は作成し、わかりやすいようにシンボリックリンクを張る

mkdir /usr/local/sonarqube
mv /usr/local/src/sonarqube-5.4 /usr/local/src/sonarqube/
ln -s /usr/local/src/sonarqube-5.4 sonar

JAVA同様に環境変数SONAR_HOMEを設定します。

touch /etc/profile.d/sonarenv.sh
touch /etc/profile.d/sonarenv.csh
vim /etc/profile.d/sonarenv.sh
export SONAR_HOME=/usr/local/sonarqube/sonar
export PATH=$PATH:$SONAR_HOME/bin/linux-x86-64
vim /etc/profile.d/sonarenv.csh
setenv SONAR_HOME=/usr/local/sonarqube/sonar
setenv PATH=$PATH:$SONAR_HOME/bin/linux-x86-64

SonarQubeでMySQLを使うので、SonarQubeの設定を書き換えます。

vim /usr/local/sonarqube/sonar/conf/sonar.properties

 #--------------------------------------------------------------------------------------------------
 # DATABASE
 #
 # IMPORTANT: the embedded H2 database is used by default. It is recommended for tests but not for
 # production use. Supported databases are MySQL, Oracle, PostgreSQL and Microsoft SQLServer.

 # User credentials.
 # Permissions to create tables, indices and triggers must be granted to JDBC user.
 # The schema must be created first.
 sonar.jdbc.username=sonar // mysqlのユーザ
 sonar.jdbc.password=sonar // mysqlのパスワード

 #----- Embedded Database (default)
 # H2 embedded database server listening port, defaults to 9092
 #sonar.embeddedDatabase.port=9092


 #----- MySQL 5.x
 # Only InnoDB storage engine is supported (not myISAM).
 # Only the bundled driver is supported. It can not be changed.
 sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance // コメントアウトを外す

serviceから起動できるように、"/usr/local/sonarqube/sonar/conf/wrapper.conf"を編集

vim /usr/local/sonarqube/sonar/conf/wrapper.conf
wrapper.java.command=/usr/local/java/latest/bin/java

init.d以下にシンボリックリンクを張る

ln -s /usr/local/sonarqube/sonar/bin/linux-x86-64/sonar.sh /etc/init.d/sonar

サービス開始とサービス停止

service sonar start
service sonar stop

SonarQubeへ接続 http://192.168.56.10:9000/

初期ユーザはID/PASS共にadminです。

これで下準備及びWEB画面の設定が完了です。

ここから解析をしていくのですが、冒頭でも説明したように、SonarQubeは色々な言語をサポートしています。 PHPに関してはPluginを導入する必要があります。 一緒に日本語パッケージもあるのでインストールしましょう。

SonarQubeに今回解析の対象となるPHPPluginを導入 Administration > System > Update Center

以下Pluginを導入 ・PHP ・Japanese Pack

これが導入されればPHPの解析及び日本語化が可能となります。

更に解析にはSonar scannerというツールが必要になります。 このScannerで解析した結果をMySQLに突っ込んで、それをWEBから見るという仕組みになります。

それではScannerのインストールです。

cd /usr/local/src/
wget https://sonarsource.bintray.com/Distribution/sonar-scanner-cli/sonar-scanner-2.5.zip
unzip sonar-scanner-2.5.zip

コピーを取って/usr/lcoalへ移動、リンクを貼る

cp -R sonar-scanner-2.5 /usr/local/sonarqube/
cd /usr/local/sonarqube/
ln -s sonar-scanner-2.5 sonar-scanner

※srcディレクトリに不要だと思ったらmvでも良いと思います。 自分は何をインストールしたのかを見ておきたいので、容量が圧迫されない限りsrcディレクトリはDLしたファイルそのまま残ってます。。。

対象のソース配下にprojectファイルを設置することによって解析が可能となります。

vim /var/www/app/src/sonar-project.properties
sonar-project.properties
# Required metadata
sonar.projectKey=org.sonarqube:php-test-scanner
sonar.projectName=PHP :: test php project :: SonarQube Scanner
sonar.projectVersion=1.0
# Comma-separated paths to directories with sources (required)
sonar.sources=src
# Language
sonar.language=php
# Encoding of the source files
sonar.sourceEncoding=UTF-8
# exclusions
sonar.exclusions=src/vendor/**,src/tests/**

内容は見ればわかると思いますが、解析するディレクトリ、プロジェクト名(任意の名前)、言語の設定やファイルのエンコード、exclusionsは除外ディレクトリですね。

List Distributions
sonar.exclusions 除外設定
sonar.language 対象言語。 省略化するとマルチ言語として処理
sonar.projectKey プロジェクトを識別するためのキー。使用している環境で一意(ユニーク)にならなければならない。使用可能文字は アルファベットの小文字、数字、'-'、'_'、'.'、':' の記号。ただし、数字のみは不可。
sonar.projectName プロジェクト名。 Web 上でのプロジェクトの表示名となる。
sonar.projectVersion プロジェクトのバージョン
sonar.sourceEncoding ソースファイルの文字コード
sonar.sources ソースのあるフォルダー。プロジェクトファイルからの相対パスで指定
sonar.exclusions 除外するディレクトリ及びファイル

解析の時には対象のディレクトリまで移動し、sonar-runnerを実行します。

cd /var/www/app/src/
/usr/local/sonarqube/sonar-scanner/bin/sonar-runner
INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
INFO: More about the report processing at http://localhost:9000/api/ce/task?id=AVODDZ_yE0cjnG_A0amQ
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 43.834s
INFO: Final Memory: 43M/255M
INFO: ------------------------------------------------------------------------

上記SUCCESSが出力されれれば完了となります。

先ほども書きましたが、SonarQubeはソースをSonarQube Scannerで読み取り、DBに保存、SonarQubeでDBから解析情報を取得し、表示するというのが一連の流れです。

ScannerがSUCCESSとなった後はWEB画面にsonar-project.propertiesで設定したプロジェクト名が表示されているはずです。

これでDuplication(重複コード)や規約に添っていない危険なコードの検出ができているので、確認しながら潰していくようにします。 CIとの連携はまた別途!

WEBで管理できる上に該当部分だけピックアップしてくれ、担当者やコメント、ステータス管理までできるから重宝しています!

もしPHPの静的解析が必要な場合は、一度試してみてください!