さくらVPSのCentOS7にTomcat8をインストール

せっかくさくらVPSを契約したので(まだお試し期間中ですが)、Tomcatを入れてみることにしました。昔WindowsではTomcatをよく使ってたんですが、Linuxでやると勝手が違いました。

 

まとめ

  • yumリポジトリ―にないっぽい?ので、手動でダウンロードしてインストール
  • systemctlのしきたりにのっとってサービスに登録
  • firewalldで8080番ポートを開ける
  • Tomcat起動が無茶遅いことへ対処
  • 80番でアクセスしたいのでfirewalldでポートフォワードの設定

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

このあたりを参考にしてやりました。

 TomcatのWebサイトに書いてるダウンロードURLからダウンロードして、展開するだけっぽいです。お手本にならってインストール先は /opt 以下に。今回はrootじゃなくてちゃんとtomcatユーザー作りましたよ。

ここではダウンロード、展開とsystemctlのサービスの登録までで、ポート関連は次。

 

8080ポートを開ける

Tomcatのデフォルトポートは8080なので、8080番ポートを開ける必要があります。ここを参考にしてやりました。

CentOS7 で Tomcat のポートを解放する Firewall 設定方法: 私的な技術メモ

 

パスを間違えてて無駄にはまる

/etc/systemd/system/tomcat.service のExecStartとかに記述するtomcatのパスを間違えてて、無駄にはまりました。Linuxビギナーだとエラーを見てもtomcat.shが呼ばれてさえいないということが分からないんですよね~

Tomcat自体のログはTomatをインストールしたディレクトリの下の log/catalina.out なので、少なくともTomcatが起動されようとしていれば、ここにログが記録されるはずです。↓Tomcatのログの場所

 /opt/apache-tomcat-xxx/logs/catalina.out

 

とりあえず、さくらVPSのCentOS7上でTomcat8を起動して、うちのブラウザからアクセスできました。

 

Tomcatの起動が無茶遅い

一応ブラウザからアクセスできたはできたんですが、Tomcatを再起動したときとかの起動が無茶苦茶遅いです。catalina.outを見てみると、ROOTのデプロイ処理のとこで5分くらい止まっています。

 
...
23-Nov-2017 00:49:05.236 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
23-Nov-2017 00:49:05.237 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.23
23-Nov-2017 00:49:05.245 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/opt/apache-tomcat/webapps/ROOT] ←ここで5分ぐらいフリーズ
23-Nov-2017 00:54:32.464 WARNING [localhost-startStop-1] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [326,951] milliseconds. ←セッションID作成に326秒もかかってる
23-Nov-2017 00:54:32.501 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/opt/apache-tomcat/webapps/ROOT] has finished in [327,256] ms
...

 

というわけでエラーメッセージでぐぐったら、回答発見。グーグルさん便利だわ~

java - Tomcat 8 hangs on startup while deploying webapp. Possibly related to entropy generation - Server Fault

HowTo/FasterStartUp - Tomcat Wiki

セッションIDの初期化に使われるSecureRandomのrandomというのが無茶苦茶遅いらしい。このアルゴリズムをあまり厳密でない?urandomにすればOKとのこと。

 

 JREjava.securityを書き換えてもいいらしいけど

乱数生成によるJVM遅延に対処する | Java好き

 

ここでは、以下のページを参考にTomcatにわたすJVMのパラメータで指定することにしました

How To Install Apache Tomcat 8 on CentOS 7 | DigitalOcean

 

 /etc/systemd/system/tomcat.service に以下の1行を追加

[Unit]
Description=Apache Tomcat 8
After=syslog.target network.target

[Service]
User=tomcat
Group=tomcat
Type=oneshot
PIDFile=/opt/apache-tomcat-xxx/tomcat.pid
RemainAfterExit=yes

Environment='JAVA_OPTS=-Djava.security.egd=file:/dev/./urandom'

ExecStart=/opt/apache-tomcat-xxx/bin/startup.sh
ExecStop=/opt/apache-tomcat-xxx/bin/shutdown.sh
ExecReStart=/opt/apache-tomcat-xxx/bin/shutdown.sh;/opt/apache-tomcat-xxx/bin/startup.sh

[Install]
WantedBy=multi-user.target

 

Tomcatに80番ポートでアクセスする

Apache(HTTPサーバー)と連携とかさせずに、Tomcat単体で運用したいと思ったのですが、Tomcatのserver.xmlのポートを8080から80に変えるだけじゃダメっぽい。この記事によると、80番は特別なものらしく、ユーザ権限では使わしてくれないらしい。

Tomcatサーバに80番ポートでアクセスする。 | 三度の飯とエレクトロン

ポートフォワードでやればいいらしいけど、iptablesじゃなくてfirewalldの例が見つからない。Tomcatの例そのものはなかったけど、このあたりを参考にやりました。

centos7 - How to port forward with firewalld depending on source IP - Server Fault

CentOS7のfirewalldをまじめに使うはじめの一歩(systemdも少し) - Qiita

https://fedoraproject.org/wiki/Firewalld?rd=FirewallD

 

[root@xxx ~]# firewall-cmd --permanent --zone=public --add-forward-port=port=80:proto=tcp:toport=8080 ←このコマンドで追加
success
[root@xxx ~]# firewall-cmd --list-all --zone=public
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh openvpn http tomcat
  ports:
  protocols:
  masquerade: yes
  forward-ports: port=80:proto=tcp:toport=8080:toaddr= ←追加されてるぽい
  source-ports:
  icmp-blocks:
  rich rules:
[root@xxx ~]# cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <service name="openvpn"/>
  <service name="http"/>
  <service name="tomcat"/>
  <masquerade/>
  <forward-port to-port="8080" protocol="tcp" port="80"/> ←設定ファイル上でも追加されてるっぽい
</zone>
[root@xxx ~]# firewall-cmd --reload
success

 

これでめでたく、80番ポートでTomcatにアクセスできました!

Tomcatのsever.xmlはいじってなくてproxyPortの記述とかしてないんですが、まだhelloサーブレットぐらいしか作って動かしてないので、もしかしたら必要なのかも。

あと、この前にApache(tomcatじゃなくてhttpd)が動いてるときはsystemctlでhttpdを停止して自動起動も無効にしておきます。

 

(追記)ルールを削除する場合は、addの部分をremoveにしてやるとOKでした。あと--list-allコマンドで表示されるのはリロード後かも。

[root@xxx ~]# firewall-cmd --permanent --zone=public --remove-forward-port=port=80:proto=tcp:toport=8080

参考 Introduction to FirewallD on CentOS

To remove the rules, substitute --add with --remove. For example...

 

作ったアプリの配置

自分で作ったアプリは、Tomcatをインストールしたディレクトリの下のwebappの下にディレクトリを作って、その下に必要なファイルをおけば、他に設定を記述しなくても動きます。

 

/opt/apache-tomcat-xxx/webapps

     docs/

     exampes/

     ...

     web1/   ←webappsの下に自分のフォルダを作る

         hoge.html

         hoge.jsp

         WEB-INF/

              classes/

 

web1というディレクトリを作って、その下にhoge.htmlを作ったら、ブラウザから

http://xxxxx/web1/hoge.html

のURLでアクセスできます。

サーブレットなどJavaのクラスファイルはWEB-INF/classes以下に置きます。サーブレットもWebアノテーション( @WebServlet("/hello")とか )使えますし、比較的簡単。

 

さくらVPSでCentOS7でOpenVPNを構築

最近ドラゴンクエストライバルズというゲームにはまってますが、このゲーム海外からはプレイできないみたいです。今度海外へ行ったときにもゲームをできるように、日本でVPNサーバを立ててみることにしました。なお、商用VPNサービスを利用するのがてっとり早いのですが、いろいろ試してみたかったので。

 

VPSにCentOS7のインストール

というわけで、とりあえずさくらのVPSを契約しました。OSが選択できるようですが、ここではデフォルトのCentOSの新しい版の7を使いました。最初のOSのインストールまではここを見てやりました(第2回まで)。

knowledge.sakura.ad.jp

自分ちのクライアントPCはWindows10ですが、CUIクライアントにはputty、ファイル管理にはWinSCPを使いました。

なおとりあえず実験なのでイチイチユーザーを作らずに全部rootでやりました。

 

OpenVPNのインストールと鍵の作成とか

ググったらいくつかやり方を書いてる人がいたのでが、いくつか見た中で分かりやすかったので、この手順でやりました。

 

How to setup OpenVPN on CentOS (Server side and Client side)

https://www.hugeserver.com/kb/how-to-config-openvpn-linux-server/

 

なお、さくらVPSでCentOS7をインストールした場合、SELinuxをオフというのはデフォルトでオフだったので、この設定は不要でした。

ファイルの編集はnanoエディタ?でコンソール上で編集とか辛そうだったので、WinSCP + 秀丸を使ってやりました。サーバ上のファイルを直接開く気分で編集可能です。

 

CentOS7ではファイアウォールに新しいfirewalldというのを使っていて、上の記事ではfirewalldをとめてiptabalesを使うやり方にしてるんですが、なんとなくfirewalldの方が簡単そうだったので、ファイアウォールの設定は別の記事(以下)を参考にしてやりました。

 

ファイアウォールの設定

www.webhostinghero.com

 

クライアントからのアクセス(windows pc)

クライアントはOS標準の設定でいけるのかと思ってましたが、OpenVPNというプロトコル自体が選べない?ので、やっぱり何かツールをインストールする必要があるっぽいです。

WindowsPCからのアクセスはvpnux Clientというのを使いました。以下の情報を設定して接続しました。

・サーバーのホスト名(さくらVPSの自分のVPSのサーバ)

・3つの鍵関連ファイル

上の手順のままだと3つの鍵ファイルの名前は以下になります。

ca.crt  CA証明書

client.crt  PKI証明書

client.key PKI秘密鍵

www.vpnux.jp

このクライアントは必要な情報が明確でシンプルでけっこう使いやすい気がしました。あと、サーバー側もputtyで監視しながらやりたかったので、VirtualBox上のWindowsにvpnux Clientを入れて動かしました。

 

クライアントからのアクセス(ipad)

ipadのクライアントはOpenVPN Connectをアップルストアからインストールして使いました。鍵は上のパターンのように個別に読み込むのでなくて、鍵情報も一つのファイルにしたxxxx.ovpnというファイルを作って、それをメールなどでipadに送って、OpenVPNアプリから開くことで接続できました。

 

iPhoneiPad (iOS) でOpenVPNを使ってみよう!

https://www.openvpn.jp/document/ios-openvpn/

 

最初の設定記事 "How to setup OpenVPN on CentOS (Server side and Client side)" は途中まではよかったのですが、最後のところでなんでわざわざ鍵情報を一つのファイルに埋め込むねん?と思ったのですが、ipadとか使ってるなら1つのファイルの方がいいですね。という気はしました。

 

以上、とりあえず、後で自分がやり直すとき用忘備録的メモでした。Linuxさわるのも久々だったし、基本コマンドとか基本ツールとかの設定もあって、2日かかりました。1日目はなんとか、vpnux Clientでログインするところまではできたんですが、そっから先がわからず、iptablesの設定いじったりしてるうちに、わけわからなくなって、結局2日目はOSインストールからやり直しました。でもさくらVPSのOSインストール超早い簡単でいいすね。これを本当にパソコンにインストールとかしてたらインストールするだけで半日作業になっちゃいますからね。

 

GithubのPull Requestをローカルにフェッチ

ポケモンGO非公式APIを使ってみた - itayo’s blog で個体値チェックプログラムを作ったのですが、

最近ポケモンGOAPIが変わったらしく、

com.pokegoapi.exceptions.request.RequestFailedException: Failed to send request: SESSION_INVALIDATED

みたいなエラーがでて、PokeGOAPI-Javaでログインすらできなくなりました。

PokeGOAPI-JavaプロジェクトのWEBサイトを見てみると、最新版では対応済とのこと。

https://github.com/Grover-c13/PokeGOAPI-Java/issues/937

 

#938のPull Requestを適用すればいいらしいですが、Gitに詳しくなくて"マージされてないPull Requestを使う"というのがイマイチどうするものなのかわかりません。ググってみたところ、以下のやり方で一応動きました。

GithubのPull Requestをローカルにfetchする - 銀の人のメモ帳

Checkout github pull requests locally · GitHub

 

以下、git cloneした後の手順です。

 

gitのconfigファイル ( E:\p\.git\config )をテキストエディタで開き、以下の一行を追加します。

[remote "origin"]
url = https://github.com/Grover-c13/PokeGOAPI-Java
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

 

情報をサーバーから取得します。

 

E:\p>git fetch
remote: Counting objects: 12094, done.
remote: Compressing objects: 100% (28/28), done.
remote: Total 12094 (delta 4988), reused 5012 (delta 4985), pack-reused 7072
Receiving objects: 100% (12094/12094), 4.79 MiB | 2.28 MiB/s, done.
Resolving deltas: 100% (6271/6271), completed with 1189 local objects.
From https://github.com/Grover-c13/PokeGOAPI-Java
* [new ref] refs/pull/10/head -> origin/pr/10
* [new ref] refs/pull/101/head -> origin/pr/101

* [new ref] refs/pull/936/head -> origin/pr/936
* [new ref] refs/pull/938/head -> origin/pr/938
* [new ref] refs/pull/94/head -> origin/pr/94
* [new ref] refs/pull/96/head -> origin/pr/96

 

#938のファイルをサーバーから取得します。

 

E:\p>git checkout pr/938
Switched to a new branch 'pr/938'
Branch pr/938 set up to track remote branch pr/938 from origin.

 

以降、Gitサブモジュールの初期化、ビルドと同様に行います。先にサブモジュールの初期化をしてから、#938を充てると、error: Server does not allow request for unadvertised object とか謎のエラーになったので、全部消してcloneからやり直しました。

 

ポケモンGO非公式APIを使ってみた

※非公式APIの利用はBANの可能性があるので、利用は自己責任で

 

最近久々にポケモンGOをやりました。

昔、ポケコンGOで個体値のチェックにPokeIVというサイトを使っていたのですが、久々に使ってみるとほとんど使えなくなってました(ごくまれに通るのですが、ほとんどサーバーエラー)。代替で1秒個体値計算とかも試してみましたが、何かメンドクサイ。ググっているとGitHubに非公式のポケモンAPIのプロジェクトがいくつもあるじゃないですか。

プログラムの知識は多少あるので、どうせなら自分でプログラムを作ってみようと思いました。多分ポケモン一覧とってきて個体値表示するだけとか簡単だろうし、 ひっそり個人でやる分にはそんなにBANの可能性も低いじゃないかなー?ということで。

やってみた手順をメモしておきます。ちなみに自分のプログラム環境はWindows10  + Javaです。

 

■プロジェクト選び

GitHubでPokemonで検索するといろいろ出てきますが、私はほぼJavaしか使えないのでJavaのプロジェクトで、比較的人気があり、最近も更新されているのを選びました。

 

PokeGOAPI-Java

https://github.com/Grover-c13/PokeGOAPI-Java

 

■Gitクローン

まずやるべきことは、ソースをダウンロードしてビルドして、利用したいjarファイルを作ることです。この環境設定にけっこうてこずりました。Githubからのクローンですが、submoduleなんとかとかしないといけないらしく、自分が使ってるIDEだとやり方がよくわからなかったので、コマンドラインで使えるツール(公式のGitクライアントのWindows版)をダウンロードして利用しました。

https://git-scm.com/

 

作業を行う場所ですが、Windowsだと深い階層にプロジェクトを置いてビルドするとエラーになるため(後述)、今回はドライブ直下の短めの場所にディレクトリを切って作業を行いました。

具体的には、PokeGOAPI-Javaをクローンしてくる場所を "E:\p"にしました (Eドライブ直下のpディレクトリ)。

 
C:\Users\itayo>git clone https://github.com/Grover-c13/PokeGOAPI-Java E:\p
Cloning into 'E:\p'...
remote: Counting objects: 8022, done.
remote: Total 8022 (delta 0), reused 1 (delta 0), pack-reused 8021
Receiving objects: 100% (8022/8022), 10.00 MiB | 3.67 MiB/s, done.
Resolving deltas: 100% (4099/4099), done.
 
 
※最新版パッチの適用
2016/10/26現在、ポケモンGOAPIが新しくなったらしく、ログインもできなくなってました。次のステップの前に現状以下が必要(が、この手順は近いうちにすぐ不要になると思われる)
 
 

■Gitサブモジュールの初期化

次に、PokeGOAPI-JavaのWebサイトで解説されてるように、submoduleの初期化を行います。

 

C:\Users\itayo>E:

E:\>cd p

E:\p>git submodule update --init
Submodule 'library/src/resources/protobuf' (https://github.com/AeonLucid/POGOProtos.git) registered for path 'library/src/resources/protobuf'
Cloning into 'E:/p/library/src/resources/protobuf'...
Submodule path 'library/src/resources/protobuf': checked out '3f7b2bb6888de1ec45f0e84a8cb1ceba5e27e237'

 

ちなみにこのサブプロジェクトは通信で利用するポケモンのデータが定義されており、Google Protocol Buffersというツールが利用されています。

 

■ビルド

ビルドはgradleが利用されています。Windows上でビルドするときはw付きのgradlew.batを叩きます。gradleがわらわら必要なものを自動的にダウンロードしてきて、ビルドが行われます。

 

E:\p>gradlew library:build
Downloading https://services.gradle.org/distributions/gradle-3.0-bin.zip

....

:library:check
:library:build

BUILD SUCCESSFUL

Total time: 1 mins 32.489 secs

 

 

ビルドの結果、必要なjarファイルが以下の場所に生成されます。この-all-xxx.jarを自分で作るJavaプロジェクトのクラスパスに指定します。
E:\p\library\build\libs

  PokeGOAPI-library-all-0.4.1.jar

  ...

 

■ファイル名が長すぎるエラーについて

上のように浅い階層にブツを置いておかないと、ビルドでこんなエラーになります。このエラーの解決で何時間もハマりました。

 

Execution failed for task ':library:generateProto'.
> java.io.IOException: Cannot run program "C:\Users\itayo\.gradle\caches\modules-2\files-2.1\com.google.protobuf\protoc\3.0.0-beta-3\7fd402d66301a053e4d8018e8f91da03839e8f9c\protoc-3.0.0-beta-3-windows-x86_32.exe": CreateProcess error=206,  ファイル名または拡張子が長すぎます。

 

ググってみると、 Windowsの最大ファイル名の長さが260文字までであることが原因らしいです。

 

How to fix "The filename or extension is too long" ? #264
https://github.com/jabbink/PokemonGoBot/issues/264

During set-up receiving error=206 filename too long #454
https://github.com/jabbink/PokemonGoBot/issues/454

 

レジストリをいじったら260文字以上もOKって記事があったので、まずこれを試してみたんですが、

How to Make Windows 10 Accept File Paths Over 260 Characters

同じエラーが出るのであきらめて、作業するディレクトリの階層を浅くしました。

 

あと、今回は不要でしたが、gradleのリポジトリも浅い階層にしたければ、GRADLE_USER_HOME環境変数で指定できます。何も指定しないデフォルトはユーザー/.gradleディレクトリ。

 

■自分のプログラム開始

さて、ビルドが終わりようやく、プログラムに入ります。私はだいたいEclipseを利用しているので、今回もEclipseで作りました。普通のJavaプロジェクトを作成し、先ほどのビルドで生成されたPokeGOAPIのjarファイル(PokeGOAPI-library-all-0.4.1.jar)を、ビルドパスに追加します。お好みでjavadoc.jarやsources.jarもアタッチできます。

 

で、さぁログインしようとかと思ったのですが・・・サンプルをコピってログインしようとしたのですが、何やらエラーが出ます。

 

Exception in thread "main" com.pokegoapi.exceptions.request.RequestFailedException: com.pokegoapi.exceptions.request.HashException: com.pokegoapi.util.hash.legacy.LegacyHashProvider is no longer supported
at com.pokegoapi.util.AsyncHelper.toBlocking(AsyncHelper.java:36)
at com.pokegoapi.main.RequestHandler.sendServerRequests(RequestHandler.java:139)
...

 

■PokeHashキーの購入

サンプルのExampleConstants#getHashProviderで利用されている、PokeHashProviderクラスのjavadocを見ると、無料じゃもうログインできないよ、こっち見てねと書いてました。

 

Hash provider on latest version, using the PokeHash hashing service. This requires a key and is not free like the legacy provider.
See Also: https://hashing.pogodev.org/

 

このサイトでpokehashkeyとやらをゲットする必要があるようです。全然動かないよ!買ったのにキーが届かないよ!みたいな書き込みもあって、ちょっとどうしようかなーとも思ったのですが、ここでやめるのも何なので一番安いやつ(HashBuddy 150 RPM)を買ってみました。Paypal支払いで3.95€(約500円)でした。

 確認メールがすぐ届き、数分後にPokeHash Keyを記載したメールが送られてきました。

 

 ■プログラム再開

で、ゲットしたPokeHashキーを使ってプログラムを再開。ログインできた!とりあえず一安心です。

で、所有ポケモンのIVの一覧を表示するプログラムもちゃちゃっと作れました。こんな感じ。

f:id:itayo:20170729153115p:plain

 とりあえずやりたいことはできました。が、これを本アカで使うかとなると、ちょっと覚悟がいりますね・・・

 

今回は、はじめてgitをコマンドラインで利用、はじめてのgradleの利用、Protocol Buffersとか聞いたのもはじめて、とはじめてのことをいろいろ経験できてよかったです。あと久々にプログラムして少し楽しかったです。