テーブル単位のmysqldump

めちゃくちゃ基礎的な内容なのですが、備忘録を兼ねてメモしておく

DBまるごと

よくやるmysqldumpコマンド

1
$mysqldump -u root -p development_db  > db_backup.sql

テーブル単位

tオプションは、「テーブル作成情報(CREATE TABLE ステートメント)を書き込まない」という内容を指す
migrationなどで先にテーブルを作った場合とかに有効活用できる

1
$mysqldump -u root -p -t development_db my_table1 my_table2 > table_backup.sql

上のコマンドのようにテーブル名は複数指定可能(my_table1, my_table2などが該当)

リストア

1
$mysql -u root -p development_db < summaries.sql

BuildConfigを使用して、環境ごとに値を取得仕分けてみる

はじめに


WebAPIと連携するようなAndroidアプリを作っているのですが 開発と本番で接続先を切り替える必要が出てきました。

それのライトな対応方法をメモ

build.gradleを編集


以下のような形で記載

1
2
3
4
5
6
7
8
buildTypes {
  debug {
    buildConfigField "String", "API_URL", "\"http://api-dev.hoge.co.jp\""
  }
  release {
    buildConfigField "String", "API_URL", "\"http://api.hoge.co.jp\""
  }
}

ソースコード側


以下のように特に気にせずBuildConfigを参照すればよい

1
String url = BuildConfig.API_URL

ビルド環境に応じた値が取得できる

できたけど・・・


これぐらいなら、まぁbuild.gradleでいいやという気がするもののパラメータ増えたら収拾つかなくなる予感

真面目にやるならBuild Variantsを使うほうがよいかと思います

Heroku上でJersey + Jetty + Gradleを動かす

はじめに


JavaでRestfulといえば、JAX-RSが有名ですね。

それを扱いやすくしたFrameworkといえば、Jerseyになります。
これをHerokuで動かすようにしてみます。

ついでにオワコン臭漂うmavenを辞めて、Gradleでビルドができるようにもしてみます

目標


以下ができていること

  • Heroku上でJerseyが動くこと
  • HerokuではJettyがサーブレット・コンテナとして動くこと
  • ビルドツールには、デフォルトのmavenではなくGradleであること

Jersey


まずはmaven ArchTypeから必要なファイルを準備

ここを参考にすると、ArchTypeは2種類あることが分かります。

今回はJettyで動かすので、サーブレットコンテナ用のものを使います

1
mvn archetype:generate -DarchetypeGroupId=org.glassfish.jersey.archetypes -DarchetypeArtifactId=jersey-quickstart-webapp -DarchetypeVersion=2.17

必要項目を聞かれますので、以下のような感じで入力していきます

1
2
3
4
Define value for property 'groupId': : kurobara
Define value for property 'artifactId': : kurobara
Define value for property 'version': 1.0-SNAPSHOT:
Define value for property 'package': kurobara: kurobara

成功すれば、以下の構成になります

1
2
3
4
5
6
7
8
9
10
11
├── pom.xml
├── src
│   └── main
│       ├── java
│       │   └── kurobara
│       │       └── MyResource.java
│       ├── resources
│       └── webapp
│           ├── WEB-INF
│           │   └── web.xml
│           └── index.jsp

mavenの削除


普通に考えると、mavenを使わなければpom.xmlを残してもよいかと思います(自分も最初は思いました) Herokuではmavenがデフォルトで使われますので、削除してしまいます

1
rm pom.xml

どうやら、mavenとGradleの両方のビルドファイルが存在するとHerokuではmavenのものが最優先で使われるようです

Gradleの追加


以下の内容をbuild.gradleに記載します

このファイルのミソはtask stage(dependsOn: ['clean', 'installApp'])を記載していることです。 Herokuではこのタスクが必要なようです。

公式を参考にしました。

多分、必要無いと思いますが念のためgradlewも用意しました(自分は一応、これもファイルに追加しています)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
apply plugin: "java"
apply plugin: "war"
apply plugin: "jetty"
apply plugin: 'application'

group = "kurobara"
version = 1.0
sourceCompatibility = 1.7
mainClassName = "kurobara"
applicationName = "kurobara"

def defaultEncoding = 'UTF-8'
[
  compileJava,
  compileTestJava,
  javadoc
]*.options*.encoding = defaultEncoding

repositories {
  mavenLocal()
  maven { url "http://maven.seasar.org/maven2" }
  mavenCentral()
}

dependencies {
  compile 'org.eclipse.jetty:jetty-server:9.2.10.v20150310'
  compile 'org.eclipse.jetty:jetty-webapp:9.2.10.v20150310'
  compile 'org.glassfish.jersey.core:jersey-server:2.17'
  compile 'org.glassfish.jersey.containers:jersey-container-servlet-core:2.17'

  testCompile 'junit:junit:4.10'
}

task stage(dependsOn: ['clean', 'installApp'])

[jettyRun, jettyRunWar]*.httpPort = 8090
[jettyRun, jettyRunWar]*.contextPath = 'kurobara'


task wrapper(type: Wrapper) {
  gradleVersion = '1.6'
}

Jettyの準備


最低限度の内容でJettyサーバが動くようにします

mainメソッドにサーバの実装を記載します。

Gradleに記載したように、これがmainClassになります(mainClassNameを参照)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;

public class Main {

  public static void main(String[] args) throws Exception {
      Server server = new Server(Integer.valueOf(System.getenv("PORT")));

      WebAppContext context = new WebAppContext();
      context.setServer(server);
      context.setContextPath("/");
      context.setResourceBase("src/main/webapp");
      context.setClassLoader(Main.class.getClassLoader());
      server.setHandler(context);

      server.start();
      server.join();
  }
}

以下の構成になるようにMainクラスを配置します

1
2
3
4
5
6
7
8
9
10
11
12
├── build.gradle
├── src
│   └── main
│       ├── java
│       │   └── kurobara
│       │       ├── Main.java <- これを追加
│       │       └── MyResource.java
│       ├── resources
│       └── webapp
│           ├── WEB-INF
│           │   └── web.xml
│           └── index.jsp

動作確認


まずは、テストが動くかどうか確認

1
2
$gradle clean
$gradle test

次にアプリをビルドし、サーバを起動

1
2
3
$gradle clean
$gradle build
$gradle jettyRunWar

以下のコマンドでGot it!が返却されるか確認

1
curl -v http://localhost:8090/kurobara/webapi/myresource

Heroku環境用の準備


Herokuで動かすJavaのバージョンを指定するsystem.propertiesを作成
(以下のようにとりあえず確実に動作するバージョンを指定)

1
java.runtime.version=1.7

Procfileに記載するスクリプトファイルの確認

1
$gradle stage

こういう形にビルド結果が出力されているので、アプリケーション起動スクリプトのファイルパスを確認する

1
2
3
4
5
6
7
8
9
10
11
12
├── build
│   ├── classes
│   │   └── main
│   │       └── kurobara
│   │           ├── Main.class
│   │           └── MyResource.class
│   ├── dependency-cache
│   ├── install
│   │   └── kurobara
│   │       ├── bin
│   │       │   ├── kurobara <- これが起動用ファイル
│   │       │   └── kurobara.bat

生成したスクリプトファイルパスをProcfileに記載

1
web: ./build/install/kurobara/bin/kurobara

不要ファイルを無視するように.gitignoreを作成
(Herokuへのデプロイはgitのため)

1
2
build/
.gradle/

最終的に以下の構成になります

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── .gitignore
├── Procfile
├── build.gradle
├── src
│   └── main
│       ├── java
│       │   └── moonstruckdrops
│       │       ├── Main.java
│       │       └── MyResource.java
│       ├── resources
│       └── webapp
│           ├── WEB-INF
│           │   └── web.xml
│           └── index.jsp
└── system.properties

Herokuへdeploy


herokuへloginする

1
2
$ brew install heroku
$ heroku login

サーバへデプロイする

1
2
3
4
5
$ git init
$ git add .
$ git commit -m "Ready to deploy"
$ git remote add heroku your_heroku_path
$ git push heroku master

以下のコマンドでGot it!が返却されるか動作確認

1
$curl -v http://your_app.herokuapp.com/webapi/myresource

感想


書くと簡単でしたが、実際にやってみると思った以上に嵌まりどころが多かった

特に以下が盛大な罠でした

  • Procfileに書くファイルはどれなのか
  • heroku logsを確認するとapp crashと表示されて何がなんだかわからんかったこと
  • app crash起因ですがweb.xmlはいじらなくてもいいのか?なんて思ったこと

一度環境さえ準備できれば開発に専念できるようになるので、非常に楽ですね

なぜApacheとTomcatを連携させるのか

はじめに


同僚とApacheとTomcatって何で連携させるんだっけ?
という話が出たので備忘録的に記載しておきます

ぶっちゃけ、今更感がすごい内容ですが・・・

Apache


ざっくり言うと、クライアントのブラウザからアクセスし、サービスを提供するためのWebサーバソフトウェア

Tomcat


こちらもざっくり言うと、以下のもの

  • 「サーブレット・コンテナ」(Servlet等を動作させるために必要なWebアプリケーションサーバ)
  • Servletのインスタンス管理やセッションの管理
  • Webサーバ機能有り(主に開発とデバッグ用)

連携理由


開発、デバッグ用途としてWebサーバ機能があるので、問題はないのですが そもそもとして、ApacheなどのWebサーバの性能と同等に捌けるかは疑問があったりするところ

なので、以下の処理分担としたほうが効率よく捌けるため連携をさせることが多い

  • 静的コンテンツ(HTMLや画像ファイルなど)の処理はApacheが担当(何故なら、高速でTomcatに比べて高速に処理できるから)
  • 動的コンテンツに関しての処理をTomcatが担当

所謂、餅は餅屋ということですな

APIを作る際のAPIバージョンに関するメモ

はじめに


APIを作るときにどうするか?を開発チーム内で議論したので、備忘録的なメモ

発端となった会話は、こんな感じだったはず

「マイクロアーキテクチャなサービスを作ったときってAPIを作ると思うけど、ライフサイクルって考えてる?」
「APIを利用するフロントは更新できるけど、APIは依存されるものが多いから簡単には更新できないよね?」
「APIってモバイルアプリからも利用した場合、修正しづらくない?バージョン管理でもするの?」

APIの種別


以下の3つぐらいになりそう

  • 外部公開向け
  • モバイルアプリ向け
  • webサービス向け

外部公開向け


  • API変更の影響が大きい
  • ドキュメント更新必須
  • 利用者が離れるのでドラスティックな変更はできない
  • 利用者への周知が必須

モバイルアプリ向け


  • アプリのみが影響を受けるので、API変更における影響は少ない
  • アプリバージョンによるので自由にAPI更新ができない
  • OSバージョンによってアプリのアップデートができないことが多いので、更新によって使えなくなる可能性有
  • 更新API対応のアプリであっても、アプリが更新されることは無いと思ったほうがよい

webサービス向け


  • クライアントもAPIに合わせて最新にできるので、変更しやすい
  • キャッシュされたクライアントのコードとのデータ不整合が起きやすい
  • キャッシュに振り回される(iOSのwebview等)

バージョニング方式


APIのバージョン管理方式は以下のものが採用される傾向にある

  1. アクセス先URIそのものを大きく変更する
  2. URIにバージョンを埋め込む
  3. クエリに使用APIバージョンを入れる
  4. メディアタイプにバージョンを指定する

世間的には、2のパターンが比較的多く採用される傾向

URIにバージョンを埋め込み方式


  • 「v1」のように「v」をつけてバージョンを明確にすることが多い
  • 日付やリリースバージョン(ハッシュ等)をバージョンにするAPIもある(twillo等)
  • URIに組み込むバージョンは、メジャー番号のみを含める
  • APIの修正は、後方互換を保ちつつ対応する

バージョニングは以下のセマンティックバージョニング方式を取ることが多い

  • パッチバージョンは、ソフトウェアのAPIに変更がないバグ修正を行ったときに増える
  • マイナーバージョンは後方互換がある機能変更、特定の機能追加のときに増える
  • メジャーバージョンは後方互換が無い変更の時に増える

メディアタイプにバージョンを指定する


  • 「Accept: application/vnd.example.v2+json」のような形で規定する
  • URIがリソースを表しているので、HTTPの文法に則っている
  • 「Content-Type」の指定誤りで、サーバ、クライアント側ともにエラーになりやすい傾向

バージョン変更指針


  • APIは基本変更しないほうがよい
  • 変更は後方互換を保ちつつ対応できる場合は、マイナーバージョンアップ(可能な限りこちらを選択)
  • 後方互換が保てない修正の場合はメジャーバージョンアップ
  • レスポンスデータ整合性/整理のためであれば、バージョンは上げない(後方互換を維持し続け、ドキュメント整理で対応)

メジャーバージョンアップ指針


後方互換が保てない場合のみ実施し、バージョンアップのルールを整理してから行う

  • セキュリティ/権限などのAPI使用ルール変更
  • 認証方式の変更
  • 乱雑に作った(ルールが無い)APIを使いやすくするための整備

APIの提供終了


  • API提供終了前に提供終了日時のアナウンスをする(提供終了後、半年ほどは動かしておくこと)
  • 提供終了までにAPIを利用できなくするブラックアウトテストを数回実施する
  • API提供終了の仕様をドキュメントに盛り込んでおく(HTTPのステータスコード410(Gone)を返すなど)
  • 利用期限をAPI提供開始時に決めておく
  • 古いAPIを叩いたときに、新APIへのリダイレクトは、混乱を招くので避けたほうがよい

# モバイル向けAPIの場合、ユーザー体験に直結するので仕様として予め考えておく(モバイル向けの場合、APIの停止はトレンドを見つつ行うこと) # アプリのアップデートを促すようにしておく(強制アップデートは好まれないが、使えなくなるよりも遥かにマシ)

Linuxのログイン履歴確認

はじめに


毎度なんだっけ?ってなって思い出すのが面倒なので、備忘録的にログイン履歴確認方法を記録

最近ログインしたアカウント一覧


以下のコマンドで確認できる

1
$last

実行結果(上に行くほど最新)

1
2
3
root     tty1                          Tue May  6 18:59 - crash  (00:16)
root     tty1                          Tue May  6 18:58 - 18:59  (00:00)
reboot   system boot  2.6.32-431.11.2. Tue May  6 17:16 - 21:21  (04:04)

ログファイルから確認する


もう少し細かく見る場合はログファイルを確認する
バイナリなので中を見たいときはwhoコマンドを使用する

1
$who /var/log/wtmp

実行結果(ログファイルなので、ファイル末尾が新しい)

1
2
3
root     tty1         2014-05-06 18:58
root     tty1         2014-05-06 18:59
root     tty1         2014-05-06 19:19

各アカウントの最終ログインの一覧


普段利用していないアカウントでログインされていないか確認できる
以下のコマンドで確認できる

1
$lastlog

実行結果(各アカウントの最終ログインが表示)

1
2
3
4
5
6
7
8
ユーザ名         ポート   場所             最近のログイン
root             tty1                      **一度もログインしていません**
bin                                        **一度もログインしていません**
daemon                                     **一度もログインしていません**
adm                                        **一度もログインしていません**
lp                                         **一度もログインしていません**
sync                                       **一度もログインしていません**
shutdown                                   **一度もログインしていません**

Octopressでの画像の表示

はじめに


常々、画像ファイルってどう表示するのだっけ?と思っていたのでやってみた感じ

ファイルの格納先


octopress/source/imagesディレクトリに画像ファイルを格納する

themeで表示している画像が最初から格納されているので、ビビらず画像ファイルを格納すること

指定方法


公式を参照すればできる模様

そのため前述の格納先を相対URLで指定すると、以下の形になる

1
![hoge](/images/hoge.jpg)

こんな感じでやると画像を表示できる

TimeCapsuleのethernetを確認する

備忘録的に


TimeCapsuleのIPアドレスを固定にしたかったので、MACアドレスを調べる必要が出てきた

また同じことにならないようにメモしておく

確認方法


下記の図のように、AirMacユーティリティを開き機器のタイトルを選択すると表示されます

AirMac

AndroidのPull to Refreshをちょっとだけ調べた

はじめに


ここの内容は完全に備忘録です。
何故かというと、自分がちょっと実現したい機能があったけどできるのだろうかと調べてみたメモだからです。

普通のPull To Refresh


所謂、下向きに引っ張るとListViewが更新されるやつですね。

これはAPI Level19のSupport V4 Libraryにて機能提供されているので、簡単に実現できます。
(ちょっと癖はあるかもしれませんが・・・)

以下にデモとReferenceを記載

# デモを見ればわかりますが、扱うだけなら非常に楽に使えるような感じになっています(カスタムは面倒臭さそう)
# ぐぐれば、いっぱい記事は見つかるので詳細はそちらに譲ります

やりたかったこと


下から上にListViewを引っ張ると、ListViewが更新されること
俗に言う、bottomup to refreshってやつです

調べてみた


ライブラリは?

Android-PullToRefreshが、対応している 但し、作者がdeprecated宣言

カスタム実装は?

少し試してみた感じだと、標準機能を駆使して実現(Classの継承など)は、まず無理かも

# そもそも、そんな感じで簡単にrefreshする機能を上下を入れ替え作られているような感じにはなってなかった

ソースコードを見れば?

結論から言うと、onTouchEventでアニメーションの実施の有無など詳細な条件判定とかやっているので今のところ難しそう

SwipeRefreshLayout.java

# 追いかけた結果を書くのは割愛します

他の人はどうなの?

同じことを考える方はいらっしゃるようですね。

SwipeRefreshLayout - Pull From Bottom

ざっくり書くと、こんな感じ

  • 今のAPIだと簡単には無理
  • OSSのコードをコピーして、自前で実装した
  • ここを参考に実装すればもしかしたらできるかも

# ソースコード見た感触とあまり変わらない(´・ω・`)

ちょっと調べてとりあえず分かったこと


API叩いて直ぐ実現可能というわけではないようですね(´・ω・`)

  • クラスを継承した独自のLayoutにすればなんとかできそうかもしれない
  • 但し、onTouchEventを自前で実装するのと処理中のアニメーションを挟むため、一筋縄ではいかない
  • 実現方法の参考実装はあるので、うまくできそうかやってみればいいかもしれない
  • deprecated宣言しているが、ライブラリを使えば楽にはできる(その後のメンテナンスコストは払う必要は出そうだが・・・)

Emacsのバージョンで分岐をさせたい

発端


Emacsのバージョンを最新にしたことで色々設定が楽に書けることがわかった
そのため、最新内容を反映させた

とはいえ、下位互換もある程度保ちたかった
(全部、追従すればいいのだがそうもいかない環境もあるので)

最初に試してみた


普通にバージョンを取得してみた

1
2
3
(emacs-version)
"GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.16)
 of 2015-01-04 on hoge.local"

文字列のマッチング処理が多くなりそうで結構めんどくさい・・・

結果的にこうした


普通のmajor/minor バージョン判定を複合した条件判定するだけの関数を用意

24.3以下の判定

1
(defvar is-less-than-or-equal-24-3 (and (<= emacs-major-version 24) (<= emacs-minor-version 3)))