ISBNを操作するgem petrarcaをリリースした

はてさて、前の記事からもうひと月も経ってしまった。

その、ひと月まえの記事に書いた、Ruby 用の ISBN を操作するライブラリを RubyGems.org にリリースした。名前は petrarca。

最初のリリース(v0.2.0)が8月30日で、その後バージョンアップして現在は v0.4.0(9月8日)。とりあえず自分では満足しているので、しばらくは大きな更新はないはず。

他のライブラリにはない(ざっと調べた限りではなさそうな)機能としては、ハイフン無しの ISBN をハイフンつきに変換する Petrarca.hyphenate メソッドが日本だけでなく世界中の ISBN に対応していること。こんな感じ。

irb(main):001:0> Petrarca.hyphenate("9780061052811")
=> "978-0-06-105281-1"

国や出版社の番号はそれぞれで桁数が違うわけだけど、International ISBN Agency のページから xml ファイルでダウンロードできるのでそれを利用している。このデータはときどき更新されるらしいので、バージョンアップするとしたらその対応だな。

カテゴリー: Ruby | コメントする

RubyGems.orgにおける車輪の大発明的な話

大発明じゃなくて再発明、な。

ISBN を操作するための Ruby のライブラリを作った。

ISBN (International Standard Book Number)っていうのは、Wikipedia によると、図書の識別に使われる国際規格コードで、日本語では「国際標準図書番号」という。

別に新しいものでもなく、Ruby 用のライブラリも RubyGems.org で検索すればすでにいくつも存在することがわかる。チェックディジットのアルゴリズムも簡単だし、ちょっとやってみるのにはお手軽なのかも。そのせいかどうかは知らないけど、どのライブラリ(gem)をみてもオレのニーズとずれている(約30分の調査による)。要するに気に入らない。オレのほしいのは:

  • 妥当性の検証
  • チェックディジットの計算
  • 現行規格(ISBN13)と旧規格(ISBN10)の相互変換
  • ハイフネーション

が簡潔にできる機能であって、こういうのはモジュール関数でやればいいんだよ。わざわざ ISBN クラスなんて作る必要ないんだ。

というわけで、RubyGems.org に登録されてないのも含めると何百回目だか何千回目だかわからない車輪の再発明をしたわけだ。コードは GitHub に上げてある。

で、せっかく作ったんだから RubyGems.org にも上げておこう(みんなそう思ったんだろうな)として rake release したら「そっくりな名前の gem がすでにあるんやで」みたいなメッセージが出て拒否された。一応、既存の gem とはかぶらないことを確認して isbn_utils っていう名前にしたんだけど、似ているだけでもダメみたいだ。そうなのか。知らなかった。

そういうわけなので、とりあえず RubyGems.org での公開は保留。いい名前が思いついたら再チャレンジする。かも。

カテゴリー: Ruby | 1件のコメント

Python: BOMつきUTF-8のCSVファイルを読み込む

Windows の Excel で、CSV ファイルに UTF-8 で出力ができることを知った。調べてみると結構前からできるようになってたようだ。

Excel で作ったデータを CSV ファイルに出力して Python のスクリプトで処理する、っていうのを時々やるんだけど、今まではいったん Shift JIS で出力したのを秀丸エディタを使って UTF-8 に変換してから処理していた。スクリプトは Linux でも使うから入力データのエンコーディングは UTF-8 にしておきたいんだよね。

で、Excel が UTF-8 の CSV をはいてくれるなら面倒な変換の手間を省いてそのままスクリプトで処理できる……と思ってやってみたらエラーになった。BOM(バイトオーダーマーク)がついているのが原因らしい。UTF-8 に BOM がついてるのとついてないのがあるのは知ってたけど、気にしたことはなかった。今回初めて BOM つきの UTF-8 に出くわした。軽くググってみると Windows だけが BOM をつけるらしい。

さて、本題。

Python で BOM つきの UTF-8 を読み込むには、ファイルを開くときのエンコーディングに utf-8-sig を指定してやればいい。↓こんな感じ。

>>> import csv
>>> with open('data_with_bom.csv', encoding='utf-8-sig') as f:
...     for row in csv.reader(f):
...         if row[0]:
...             print(row[0])
...

utf-8-sig というエンコーディングは BOM なしの UTF-8 も扱える。なので UTF-8 であることがわかっていれば BOM を気にしなくていい。

>>> with open('data_without_bom.csv', encoding='utf-8-sig') as f:
...     for row in csv.reader(f):
...         if row[0]:
...             print(row[0])
...

というわけで、解決。

[余談]

コード中に if row[0]: とあるのは Excel のはいた CSV ファイルの後ろのほうにカンマだけの行がくっついてるからそれを避けるため。なんでそんな行がくっつくのかは謎。

っていうか Python って後置の if が使えないんだね。ちょっと使いにくいな。

カテゴリー: Python, Windows | コメントする

自宅ネットワーク内のコンピュータのIPアドレス割当てを固定にした

昨日、今日と2日続けて停電が発生した。午後に降った雷雨のせいだ(たぶん)。停電は短時間(1分もない)だったけど断続的に発生して、おかげで普段つけっぱなしの PC の電源が落ちた。サーバにしている PC も、だ。

雨がおさまってきたころ、PC の電源を入れて立ち上げたけど、サーバ PC で動かしている web アプリにアクセスしても繋がらなくなっていた。どうも IP アドレスが変わってしまったようだ。停電でルータの電源も落ちたからだな(たぶん)。

たいていの家庭のネットワークも同じだと思うけど、ウチのネットワークもルータの DHCP 機能を利用して各 PC に自動で IP アドレスを割り当てている。今回、ルータの電源も落ちたことで、PC を立ち上げたときに割り当てられたアドレスが変わってしまったらしい。

で、リモートではつながらないのでローカルにログインして、割り当てられている IP アドレスを確認して、hosts ファイルを修正したら繋がるようになった。

さて、もしかすると明日も雷雨で停電するかもしれないし、それでまた IP アドレスが変わってしまうようなことになればまた今日と同じ作業をしなくちゃいけなくなる。そんなのは面倒なので、DHCP で割り当てられる IP アドレスを固定にすることにした。

ルータは web インターフェイスで設定できるので、ログインしたら DHCP の設定のページで固定割り当ての設定をする。もう少し詳しく書くと、PC の NIC の MAC アドレスと、割り当てたい IP アドレスの組を登録しておくってことだ。PC が何十台もあるわけじゃないから大した作業ではない。

ともあれ、これで電源が落ちても今日みたいな作業をしなくても済むはずだ。もっと早くやっときゃよかった。

カテゴリー: misc | コメントする

Arctic Code Vault Contributor

今日、久しぶりに GitHub にアクセスしたら、自分のプロファイルの下のところに「Arctic Code Vault Contributor」なる文字があるに気がついた。

何かと思って調べてみると、GitHub のリポジトリのソースコードを北極圏の島にアーカイブして1000年後まで保管するとかいう計画に選ばれたらしい。

「GitHub Arctic Code Vault」というプロジェクトに一環で、北極圏にあるノルウェーのスヴァールバル諸島の永久凍土の地下(廃坑)のなかにマイクロフィルムに保存されたソースコード(2020年2月2日に取得したスナップショット)を保存するというものだ。今回は第1回目で、頻度は明らかにされていないものの数年に一度くらいの割合でスナップショットを保存するらしい。

それにしても、オレの書いたソースコードが1000年先まで残るのか。スゲー。

……と思いながらよく読むと、アクティブなパブリックリポジトリはすべて対象になったようだ。オレの書いたコードなんて自分でしか使わないようなのばっかなんだけど、そういうことね。いや、それにしてもすごいけど。

ところで、今回保存されたソースコードの総量は約21TBとのこと。圧縮してるのかもしれないけど、以外に少ないと感じた。まぁ、ソースコードってほとんどはテキストファイルだからそんなものなのかな。

カテゴリー: misc | コメントする

Perl 7

驚きのニュースが飛び込んできた。Perl が約25年ぶりのメジャーバージョンアップだと。

どのくらい驚いたかって、Perl の記事がほとんどないこのブログにも書いちゃうくらい驚いた。

とりあえず記録として残しておく。

カテゴリー: Perl | コメントする

Ubuntu 20.04にnodenvをインストール

GitHub のリポジトリにあるドキュメントを見ながら。

GitHub – nodenv/nodenv

まずは GitHub から clone

[email protected]:~$ git clone https://github.com/nodenv/nodenv.git ~/.nodenv

オプション扱いだけど dynamic bash extension とかいうのをビルド。nodenv がスピードアップするらしい。

[email protected]:~$ cd ~/.nodenv && src/configure && make -C src

環境変数 PATH に ~/.nodenv を追加してから、セットアップ。

[email protected]:~$ ~/.nodenv/bin/nodenv init
Load nodenv automatically by appending
the following to ~/.bashrc:

eval "$(nodenv init -)"

メッセージにあるとおり、.bashrc に記述を追加。終わったらシェルを起動し直す。

nodenv-doctor スクリプトで、ちゃんとインストールできてるか確認。

[email protected]:~$ curl -fsSL https://github.com/nodenv/nodenv-installer/raw/master/bin/nodenv-doctor | bash

OK って出たから大丈夫なんだろう。

つぎに、これもオプションみたいだけど、node-build をインストール。

[email protected]:~$ mkdir -p "$(nodenv root)"/plugins
[email protected]:~$ git clone https://github.com/nodenv/node-build.git "$(nodenv root)"/plugins/node-build

これで完了。

nodenv install -l でインストール可能な Node.js のバージョン一覧が見られる。公式サイトによると 12.18.1 が最新の推奨版なので、それをインストールする。

[email protected]:~$ nodenv install 12.18.1

nodenv global で利用するバージョンを指定。

[email protected]:~$ nodenv global 12.18.1

これで最新推奨版の Node.js が使えるようになる。

[email protected]:~$ node --version
v10.19.0

えっ??

[email protected]:~$ nodenv versions
  system
* 12.18.1 (set by /home/takatoh/.nodenv/version)

ちゃんと 12.18.1 になってるじゃないか。どういうこと?

ちょっとびっくりしたけど、なんのことはない、シェルを立ち上げ直したらできた。

[email protected]:~$ node -v
v12.18.1

おしまい。

カテゴリー: JavaScript | コメントする

Docker Compose

前回の記事では、Docker のネットワークを使って通信しながら、複数のコンテナを協働させた。

基本的には前回の記事のやり方でいいんだけど、サービスの数が増えたり、規模が大きくなってコンテナの数が増えたりすると、コンテナごとにコマンドを打って起動するのは面倒だ。コンテナによって指定するオプションも異なるので、それも覚えておく必要がある。

というわけで、そういう煩雑な部分を楽にしてくれるツールがある。それが Docker Compose だ。メインマシンである apostrophe をセットアップしたときに apt でインストールしておいた。

[email protected]:docker$ docker-compose --version
docker-compose version 1.25.0, build unknown

題材と構成

前回記事と同じ、書籍管理 web アプリと HTTP サーバ(Nginx)という構成にする。詳しくは前回記事を参照。

ビルド済みのイメージを利用する

前回ビルドした Docker イメージが残っているので、まずはそれを使ってコンテナを起動する設定を書いてみる。

Docker Compose は docker-compose.yml という名前のファイルを読み込んで、その設定どおりにコンテナを起動してくれる。今回書いた docker-compose.yml ファイルは次の通り。

version: '3'
services:

  bruschetta-back:
    image: bruschetta:1
    container_name: bruschetta-back
    restart: always

  nginx-front:
    image: nginx-c:1
    container_name: nginx-front
    restart: always
    ports:
      - 8080:80

service: の下に連なっているのが、Docker Compose で起動するコンテナだ。各設定項目は見ればだいたいわかるだろうからここでは説明は省略。ただ、docker コマンドで起動するときとは次の点が違う。

  • Docker ネットワークは自動で作ってくれるので設定不要
  • コンテナ間通信は、コンテナ名ではなく service 名で行われる

特に2つ目の挙動は docker コマンドで起動したときと違うので注意が必要だ。最初、ここでハマった。

で、これを起動するには次のようにする。

[email protected]:docker$ docker-compose up -d

起動中のコンテナの確認。

[email protected]:docker$ docker-compose ps

そして停止。

[email protected]:docker$ docker-compose stop

最後にコンテナの削除。

[email protected]:docker$ docker-compose rm

Dockerイメージをビルドして利用する

さて、今度は Docker イメージをビルドするところからやってみる。そのためには、docker-compose.yml ファイルと同じディレクトリに、イメージ作成用のファイル一式を収めたディレクトリを置いておく。こんな感じ。

[email protected]:docker$ ls -l
合計 12
drwxrwxr-x 3 takatoh takatoh 4096 5月 9 03:15 bruschetta
-rw-rw-r-- 1 takatoh takatoh 239 6月 14 13:26 docker-compose.yml
drwxrwxr-x 3 takatoh takatoh 4096 5月 14 06:19 nginx-c

そして、docker-compose.yml ファイルを次のように書き変える。

version: '3'
services:

  bruschetta-back:
    build: ./bruschetta
    image: bruschetta:1
    container_name: bruschetta-back
    restart: always

  nginx-front:
    build: ./nginx-c
    image: nginx-c:1
    container_name: nginx-front
    restart: always
    ports:
      - 8080:80

書き変えた、というか書き足したのは、build: の行だ。この行でイメージをビルドするための Dockerfile (とその他に必要なフィアル)を置いてあるディレクトリを指定している。

ビルドするには次のようにする。

[email protected]:docker$ docker-compose build

イメージができたか、確認。

[email protected]:docker$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
nginx-c             1                   c8b3966bbc31        54 seconds ago       127MB
bruschetta          1                   7d6607e796c2        About a minute ago   468MB
nginx               1.17.10             9beeba249f3e        4 weeks ago          127MB
ubuntu              20.04               1d622ef86b13        7 weeks ago          73.9MB

nginx-c:1 と bruschetta:1 がビルドされたイメージ。下の2つは元になったイメージ(Docker Hub から取ってきたもの)だ。

じゃあ、これを起動してみよう。

[email protected]:docker$ docker-compose up -d

OK。ブラウザからアクセスしてみて、期待通りに動いているのを確認できた。

カテゴリー: misc | コメントする

Dockerコンテナ間通信

Docker を使ったサービスでは、サービスを構成する各サーバプログラムをそれぞれ別のコンテナで立ち上げるのが一般的なようだ。例えばデータベース(MySQLなど)を利用する web アプリケーションであれば、つぎの3つのコンテナを立ち上げることになる:

  • データベースサーバ
  • web アプリケーションサーバ
  • HTTP サーバ

当然、これらを連携するにはコンテナ間をまたいだ通信をする必要がある。Docker にはコンテナ間通信を実現するネットワーク機能が備わっていて、各コンテナは同じ(Docker の)ネットワークに接続していれば、コンテナ名とポート番号を使って通信することができる。

今日はそのコンテナ間通信を試してみる。

題材と構成

先日作った書籍管理 web アプリと、HTTP サーバとして Nginx を前に立てる構成とする。上にはデータベースサーバが書いてあるけど、この書籍管理アプリはデータベースに Sqlite を使っているので、今回データベースサーバはなし。アプリケーションサーバと HTTP サーバ(Nginx)の2つだ。

コンテナ名は、アプリケーションサーバを bruschetta-back、HTTP サーバを nginx-c とする。この2つが Docker ネットワークで通信するわけだ。nginx-c は80番ポートをホスト側の8080ポートに接続する。ホスト側からは bruschetta-d というホスト名で nginx-c にアクセスできるようにしておく。

アプリケーションサーバ

先日作ったものなので詳細は省略。ただ、あいだに PC のリプレイスをはさんだので、イメージ名が bruschetta:1 に変わっている。内容は変更なし。

HTTPサーバ

全面に立てる HTTP サーバには、Docker Hub で公開されている Nginx こイメージをメースにして、アプリケーションサーバにつなぐための設定ファイルをコピーしたものを用意する。

Dockerfile はこう:

ROM nginx:1.17.10

COPY ./files/bruschetta-d /etc/nginx/conf.d/bruschetta-d.conf
RUN mkdir /var/log/nginx/bruschetta

CMD [ "nginx", "-g", "daemon off;" ]

この中でコピーしている Nginx の仮想ホストの設定ファイルはこうだ:

upstream uwsgi-bruschetta {
    server bruschetta-back:5000;
}

server {
    # port
    listen      80;

    # server name
    server_name bruschetta-d;

    # log files
    access_log /var/log/nginx/bruschetta/access.log combined;
    error_log  /var/log/nginx/bruschetta/error.log  warn;

    keepalive_timeout     60;
    proxy_connect_timeout 60;
    proxy_read_timeout    60;
    proxy_send_timeout    60;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://uwsgi-bruschetta;
    }

}

これで docker build した。

できたイメージの状況。

[email protected]:docker$ docker image ls
REPOSITORY          TAG                IMAGE ID            CREATED              SIZE
nginx-c             1                  6f5be529ea6d        About a minute ago   127MB
bruschetta          1                  11afb91367ae        2 hours ago          451MB
nginx               1.17.10            9beeba249f3e        8 hours ago          127MB
ubuntu              20.04              1d622ef86b13        3 weeks ago          73.9MB

Docker ネットワークの作成

Docker ネットワークの作成は docker network create コマンドを利用する。

[email protected]:docker$ docker network create nginx-network

これで nginx-network という名前の Docker ネットワークができた。つぎのようにすると様子が見える。

[email protected]:docker$ docker network ls
NETWORK ID           NAME               DRIVER              SCOPE
d0c23099f6be         bridge             bridge              local
492e64e5d79d         host               host                local
7f38bac647a0         nginx-network      bridge              local
b42cbd843632         none               null                local

nginx-network 当名前が見える。ほかにもあるけど、これらはデフォルトで用意されているものらしい。詳細は調べてない。

コンテナの起動

2つのコンテナを起動する。その際、--netowork オプションで接続する Docker ネットワークの名前(今回は nginx-network)を指定する。また、HTTP サーバのコンテナの方でアプリケーションサーバの名前を bruschetta-back と指定しているので、これを間違えないようにする。

まずはアプリケーションサーバのコンテナから。

[email protected]:docker$ docker run --name bruschetta-back --network nginx-network -d bruschetta:1

HTTP サーバ。ポートの指定も忘れずに。

[email protected]:docker$ docker run --name nginx-front --network nginx-network -p 8080:80 -d nginx-c:1

ホスト側から確認

起動したコンテナは bruschetta-d というホスト名で待ち受けているので、/etc/hosts ファイルに 127.0.0.1 を指すように記述を追加する。それができたら準備は完了だ。http://bruschetta-d:8080/ にブラウザでアクセスしてみる。

結果、期待通りにアプリケーションにアクセス、使用できることが確認できた。

参考ページ

カテゴリー: misc | コメントする

新しいPCにUbuntu 20.04 LTSをインストール

メインに使っている PC を買い替えた。

先日ダウンロードしておいた Ubuntu 20.04 LTS 日本語 Remix を DVD に焼いて(この作業は別の Windows マシンでやった)、プリインストールされていた Windows 10 は起動すらせずに上書きインストールした。ホスト名は替える前と同じ apostrophe。

OS のインストールが終わったら、とりあえずすぐに使いそうなソフトウェアだけインストールした。

  • rbenv と Ruby (2.7.1)
  • pyenv と Python (3.8.2)
  • Git
  • Sublime text
  • Dropbox
  • Tweaks
  • Docker

Python はデフォルトで入っていた(コマンドとしては python3)けど、今後を考えて pyenv を使った。Tweaks というのは、参考にした web ページにあった設定ツール。デスクトップまわりの設定ができる。

Docker についてはインストール方法を書いておこう。最初は先日 16.04 にインストールしたのを参考に作業をしたんだけどダメだった。えぇっ?と思いながらググってみると、apt コマンドでインストールできるようになっていた。

[email protected]:~$ sudo apt install -y docker.io
[email protected]:~$ sudo systemctl start docker
[email protected]:~$ sudo systemctl enable docker

ついでに docker-compose もインストール(今後使う予定なので)。

[email protected]:~$ sudo apt install -y docker-compose

あとはいくつか設定をカスタマイズして、データをバックアップサーバからコピーしてきて、ひとまずは完了。のこりは必要に応じてやっていこう。

参考にしたページ:

カテゴリー: misc, Ubuntu | コメントする