JAWS-UG 長野支部 第1回勉強会

先月、JAWS-UG 長野支部が発足しましたが、その第1回勉強会があったので参加してきました。

会場は NSEG にも良く会場を提供して頂いてるケイケンさんの会議室でした。長野駅から徒歩数分で便利です。電源も WiFi もあってすばらしいです。

AWS のアカウント取得からウェブサーバーを起動するまでのハンズオンでした。

AWS はまったく使ったことがなかったので良い機会でした。

感想等

  • EC2は簡単だった。普通の VPS っぽい。
  • サービス多すぎてよくわからない。
  • 1年間無料で使えるのは知らなかった。…けど何がどれくらい無料なのか良くわからなかった。
  • 日本語のページもあるけど、基本は英語らしい。
  • ユーザー登録フォームが日本語だったので、日本語で氏名と住所入れてみた。登録できたけど、あとでプロフィール見てみたら文字化けしてた。
  • reboot してみたけど IPアドレスは変わらなかった(たまたま?)。
  • stop & start したら IPアドレス変わった。ディスクイメージは残ってた。なぜか消えると思ってた。EBS というのが関係してる? よくわからない。
  • 固定IPアドレスは1インスタンスにつき1個無料らしい。インスタンスに紐付けないままでいると有料らしい。

よくわかってないからかもしれませんけど、下手すると膨大な料金が課金されそうで怖いです。 なんとなく、さくらのクラウドの方が安心感あります。さくらのクラウドも使ったことないのですけど。

懇親会の会場はすぐ近くの COLORFUL でした。大画面プロジェクターでサッカーの試合が上映されてました。オシャレ空間でおっさんだらけの懇親会。

グラスは長野のサッカークラブのAC長野パルセイロのマークが入ってました。

f:id:tmtms:20140706181404j:plain

スクロールバーの矢印を表示する

最近は Xubuntu を使ってますが、テーマによるのかもしれませんが、スクロールバーの端の矢印が表示されなくなってて不便なので表示する方法を調べました。

Gtk3

$HOME/.config/gtk-3.0/gtk.css を次の内容で作成

.scrollbar {
    -GtkScrollbar-has-backward-stepper: 1;
    -GtkScrollbar-has-forward-stepper: 1;
}

Gtk2

個人ごとに設定する方法はわかりませんでした。

/usr/share/themes/テーマ名/gtk-2.0/gtkrc の内容を変更

        GtkScrollbar            ::has-backward-stepper                  = 1
        GtkScrollbar            ::has-forward-stepper                   = 1
...
        GtkScrollbar::stepper-size      = 13

Ruby の Timeout.timeout に例外クラスを指定する時の注意

ちょっとハマったのでメモ。

Ruby の Timeout ライブラリを使うと、一定の時間が過ぎても終わらない処理を中断することができます。

require 'timeout'

def hoge
  sleep
end

def main
  Timeout.timeout(3) do
    hoge
  end
rescue Timeout::Error => e
  p 'main: timeout', e.backtrace.first
end

main

このスクリプトを実行すると3秒たってから終了します。

% ruby t1.rb
"main: timeout"
"t1.rb:4:in `sleep'"

バックトレースから 4行目の sleep 中でタイムアウトが発生したことがわかります。

次に Timeout.timeout を入れ子にしてみます。

require 'timeout'

def hoge
  Timeout.timeout(5) do
    sleep
  end
rescue Timeout::Error => e
  p 'hoge: timeout', e.backtrace.first
end

def main
  Timeout.timeout(3) do
    hoge
  end
rescue Timeout::Error => e
  p 'main: timeout', e.backtrace.first
end

main

main 中のタイムアウトは3秒で、hoge 中のタイムアウトは5秒です。 ですので sleep 実行中に main のタイムアウトが発生します。 この場合 main と hoge のどちらの rescue で Timeout::Error をキャッチできるのでしょうか。 プログラムを見ると sleep に近い hoge の rescue でキャッチできそうに思えますが、実行してみると次のようになります。

% ruby t2.rb
"main: timeout"
"t2.rb:5:in `sleep'"

正解は main の rescue でした。

使い勝手としてはこの方が望ましいでしょう。外側で指定されたタイムアウトが切れた場合に内側のタイムアウト処理が動いてしまっては混乱してしまいますし、使用しているライブラリが内部で Timeout を使用しているかどうかを調べないといけないというのは大変です。

Timeout ライブラリが内部でうまいことやって、利用者にとって自然な振る舞いになるような仕組みになっています。

ところで Timeout.timeout にはタイムアウト時に発生する例外クラスを指定することができます。 何も指定しないと上記のように Timeout::Error が発生します。

ところが、Timeout::Error を渡してみると動きが異なります。

require 'timeout'

def hoge
  Timeout.timeout(5) do
    sleep
  end
rescue Timeout::Error => e
  p 'hoge: timeout', e.backtrace.first
end

def main
  Timeout.timeout(3, Timeout::Error) do
    hoge
  end
rescue Timeout::Error => e
  p 'main: timeout', e.backtrace.first
end

main
% ruby t3.rb
"hoge: timeout"
"t3.rb:5:in `sleep'"

hoge の rescue が実行されてしまいました。

Timeout.timeout に例外クラスを指定した場合は、「Timeout ライブラリが内部でうまいことやってる仕組み」が働かず、そのまま指定した例外が発生するためです。

Timeout.timeout を入れ子にしてなくても、次のプログラムを実行すると、

require 'timeout'

def hoge
  sleep
rescue
  p '何か失敗した!'
end

class OreOreTimeout < StandardError
end

def main
  Timeout.timeout(3, OreOreTimeout) do
    hoge
  end
rescue OreOreTimeout
  p 'タイムアウト!'
end

main

「タイムアウト!」ではなく「何か失敗した!」が表示されます。

% ruby t4.rb
"何か失敗した!"

OreOreTimeout は StandardError のサブクラスなので rescue で拾われてしまうためです。 StandardError ではなく Exception のサブクラスにすれば rescue で拾われないため、「タイムアウト!」になります。

Timeout.timeout に例外クラスを指定する場合は注意しましょう。

Ubuntu の MySQL を標準以外のディレクトリで動かす

Ubuntu の MySQL の datadir は /var/lib/mysql です。これを別のディレクトリに変更して動かそうとするとエラーになります。

# mkdir /hoge
# mysql_install_db --datadir=/hoge
Installing MySQL system tables...
140614  8:57:23 [Warning] Can't create test file /hoge/hostname.lower-test
140614  8:57:23 [Warning] Can't create test file /hoge/hostname.lower-test

Installation of system tables failed!  Examine the logs in
/hoge for more information.
...

これは AppArmor の設定で、mysqld に対して /hoge へのアクセスが許可されていないためです。

# vi /etc/apparmor.d/local/usr.sbin.mysqld

   # Site-specific additions and overrides for usr.sbin.mysqld.
   # For more details, please see /etc/apparmor.d/local/README.
   /hoge/ r,
   /hoge/** rwk,

# service apparmor reload
 * Reloading AppArmor profiles
Skipping profile in /etc/apparmor.d/disable: usr.bin.firefox
Skipping profile in /etc/apparmor.d/disable: usr.sbin.rsyslogd

これで /hoge にデータベースを作ることができるようになりました。

# mysql_install_db --datadir=/hoge
Installing MySQL system tables...
OK
Filling help tables...
OK
...

以下駄文

  • テスト用に tmpfs 上にデータベースを作りたかったのにエラーになった。
  • /tmp とか /var/tmp とかだとエラーにならないので、ディレクトリが異なるためじゃなくて、tmpfs のせいだと思い込んだ(実は AppArmor で /tmp, /var/tmp が許可されていた)。
  • tmpfs の制限を調べても見つからない。
  • 当然 SELinux は真っ先に疑ったけど入ってなかった。
  • Ubuntu の deb じゃなくて MySQL の公式バイナリを使用したらできた(これは /usr/sbin/mysqld じゃなくて /usr/local/mysql/bin/mysqld だったため)。
  • システムコールトレースとってみたけど違いがわからない。
  • deb ファイルのパッチ読んでみたけど怪しいところはなかった。
  • Twitter でつぶやいてたら教えてもらえた。

  • AppArmor なんてものがあるのは知らなかった。SELinux がないと思って油断してた。

  • 解決

Git に対する Subversion の利点

気がついたら Git を初めて触ってからもう5年近くになってました。

それまで使ってた Subversion はもう全然使ってなくて、もう svn のサブコマンドは ls, log, co くらいしか使えません。Subversion のリポジトリを見ないといけないときは、とりあえず git svn で Git リポジトリに変換してから見たりしてます。 SCCS, RCS, CVS はもう全然わからないので、Subversion はまだ覚えてる方ですけど…。

Subversion に対する Git の利点はあちこちで述べられているので今更何も書くことはありませんが、Git よりも Subversion の方が良いこともあるので、忘れないうちに書いときます。

リポジトリ全体をコピーしなくても編集できる

リポジトリの歴史が長い場合や、頻繁に更新されるバイナリデータがあるとリポジトリが大きくなります。それは Subversion でも同様なのですが、Subversion はリポジトリ全体をローカルにコピーする必要はないので、ローカル用のディスクは作業ディレクトリ分だけで良いです。

Git は編集するためにはリポジトリ全体をコピーする必要があるので、ローカルディスクもそれだけ必要となります。git clone --depth で最新n件分のコミットだけ clone することができますが、そのようにして得られたリポジトリから元のリポジトリに対して push することはできません。

…と思っていたのですが、どうやらバージョン 1.9 からできるようになったようです。

コミットに認証が必要

Git はローカルにリポジトリがあるので、リポジトリに対して何でもできます。リモートリポジトリにプッシュ権があれば、人の名前を騙ったコミットをプッシュすることもできます。

Subversion サーバーを立てる場合は、普通はコミット時に認証を必要とするように設定するので、他人を騙ってコミットすることはできません。

[追記] Git でコミットに署名をつけることができるようです。

リポジトリ内のファイルを HTTP で簡単に得られる

Apache で Subversion サーバーを立ててる場合、専用プログラムを使わなくても、ブラウザだけですべてのブランチとタグのファイルを HTTP で取得できます。 最新のリビジョンだけで、古いリビジョンのファイルは見えませんが…。

[追記] URLのパラメータでリビジョンの指定もできるようです。

WebDAV でファイル共有できる

これも Apache でサーバーを立ててる場合ですが、Subversion 用プログラムを使わなくても、WebDAV でファイル共有できます。 Windows を使っている場合はエクスプローラーを使ってアクセスすることができます。 コミットメッセージは書けませんが、非エンジニアの人に共有ディスクと同じ感覚でファイルを置いてもらうだけでバージョン管理できるのはお手軽です。

Subversion実践入門:達人プログラマに学ぶバージョン管理(第2版)

Subversion実践入門:達人プログラマに学ぶバージョン管理(第2版)

実用 Subversion 第2版

実用 Subversion 第2版

  • 作者: C. Michael Pilato,Ben Collins-Sussman,Brian W. Fitzpatrick,宮本久仁男(監訳),朝枝雅子,浜本階生
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2009/07/27
  • メディア: 大型本
  • 購入: 6人 クリック: 45回
  • この商品を含むブログ (19件) を見る

Gitで最初のコミットをどうにかする

Git

最初のコミットの内容を変更したい

Gitで最初のコミットの内容を変更したいと思って git rebase -i <最初のコミット> とやっても、最初のコミットは出てきません。

% git log --oneline
4f4f42c 二番目のコミット
9d4876c 最初のコミット

% git rebase -i 9d4876c
pick 4f4f42c 二番目のコミット

このような場合は git rebase -i --root を指定すると良いようです。

% git rebase -i --root
pick 9d4876c 最初のコミット
pick 4f4f42c 二番目のコミット

最初のコミットの前に別のコミットを入れたい

さっきと同様に git rebase -i --root で開いて、最初のコミットを edit にします。

% git rebase -i --root
edit 9d4876c 最初のコミット
pick 4f4f42c 二番目のコミット

ここで何か変更して、git commitgit rebase --continue すると、最初のコミットの次に入ります。

% git log --oneline
94d6512 二番目のコミット
1b424b1 何か変更
14ad5e8 最初のコミット

そしてもう一度 git rebase -i --root で、コミットの順番を並び替えると、最初のコミットの前に移動できます。

% git log --oneline
c6e0a13 二番目のコミット
71e774a 最初のコミット
828ea78 なにか

または親を持たないブランチを作成して、それに rebase するという方法もあります。

% git checkout --orphan hoge            # 親を持たないブランチ
% git reset                             # ファイルが stage 状態になってるので reset
% git commit --allow-empty -m 'なにか'  # 空コミット
% git clean -fdx                        # master にあるファイルが残っているのでクリア
% git checkout master
% git rebase hoge                       # master を hoge から派生するように rebase
% git log --oneline
5cc41ab 二番目のコミット
b87ca1f 最初のコミット
0544410 なにか

ほかにもいい方法があるかもしれません。

「文字化けに関するトラブルシューティング」

ちょっと前の話ですが、こんなツイートを見かけました。

職業柄文字化けデータを見ると復元せずにはいられないので、文字化けデータを私に見せるのはやめて欲しいです。

文字化け業界に長くいると、経験上パッと見てなんで文字化けしたのかだいたいわかるようになります。 今回のは、本来 EUC-JP なのにシフトJISとして表示しちゃってる感じです。

半角カナが多い場合はだいたいこのパターンです。

% ruby -e 'puts "日本語にほんごニホンゴ".encode("EUC-JP").force_encoding("SHIFT_JIS").encode("UTF-8", undef: :replace, invalid: :replace, replace: "?")'
ニ?ワク?ヒ、ロ、?エ・ヒ・ロ・?エ

画数の多い漢字の中に半角カナが少々混じるのは、UTF-8 をシフトJISとして表示しています。

% ruby -e 'puts "日本語にほんごニホンゴ".encode("UTF-8").force_encoding("SHIFT_JIS").encode("UTF-8", undef: :replace, invalid: :replace, replace: "?")'
譌・譛ャ隱槭↓縺サ繧薙#繝九?繝ウ繧エ

$% が1文字置きに現れるのは ISO-2022-JP の ESC が落ちたか、EUC-JP の 8bit目が落ちた場合です。 ISO-2022-JP の場合は $B(B が現れます。

% ruby -e 'puts "日本語にほんごニホンゴ".encode("ISO-2022-JP").force_encoding("ASCII-8BIT").gsub(/\e/n,"?")'
?$BF|K\8l$K$[$s$4%K%[%s%4?(B
% ruby -e 'puts "日本語にほんごニホンゴ".encode("EUC-JP").force_encoding("ASCII-8BIT").bytes.map{|b| b & 0x7F}.pack("c*")'
F|K\8l$K$[$s$4%K%[%s%4

ということで、変換に伴って欠落してしまうデータはあるものの、元の文字コードが何だったのかがわかってしまえば、文字化けしたデータから元データを復元するのはそんなに難しくありません。

ですが、今回のは画像だし、フォントサイズも小さいので画数の多い字は潰れてしまって判別できなくて難易度高いです。

とりあえず文字を拾って見ます。「・」は変換できなかった文字(「・」の一部も)で、「?」は変換できたものの画像から判別できなかった文字です。

サトヌー、ハ、ャ、鮑ス・ミ。シ・ク・逾・ホ」ラ」??茱・・・ヌ、マ
ハクサ?ス、ア、・ハ、ェ、ケ、ウ、ネ、マスミヘ?゙、サ、・」
」イ」ー」イ」オヌッネッヌ莽スト熙ホ」ラ」??茱・・・ヌ、マツミア・、キ、゙、ケ。」
、ウ、ホ・ネ・?ヨ・・キ・蝪シ・ニ・」・・ー、ヌ、マ。「
、ウ、ホ、?ヲ、ハフ萃熙ホクカー・・ヘ、ュザ、癸「
フ萃熙・・?ケ、・・?・ィ、キ、゙、ケ。」
シチフ荀ホナ妤ィ、・ッ・・テ・ッ、キ、ニ、ッ、タ、オ、、。」
シ・遉ヒスセ、テ、ニソハ、゚、ハ、ャ、?萃熙・・?ヌ、ュ、゙、ケ。」

、ノ、ヲ、キ、゙、ケ、ォ。ゥ

サナハ・、ャ、ハ、、、ォ、?ヨ・タ・、・「・?ー、ヌヘキ、ワ、ヲ。ラ、・ワヘ・」
。ヨナマノ・キ・・、・チ、ホ」ト」螢凜癸?・・。」ラ」マ」メ」フ」ト。ラ、・ワヘ・」

これを単純に変換すると

残念ながら現バージョ??E裡廝?H?H筍?E?E?E任?
文??H修韻?E覆?垢海箸禄侏?H泙擦?E?
2025年発売予定のW??H?H筍?E?E?E任和弍イ靴泙后?
このト??H屮?E轡紂璽謄??E阿任蓮?
この??HΔ別簑蠅慮彊?E?E佑?泙瓠?
問題??E?E?H垢?E?E?H?E┐靴泙后?
質問の答え??E??E奪?靴討?世気ぁ?
??E腓暴召辰匿覆澆覆??H簑蠅?E?E?H任?泙后?

どうしますか?

仕淵がないか??H屮瀬ぅ▲?H阿罵靴椶Α廚?E寨?E?
「渡??E轡?Eぅ舛裡庁紕蝪瓠?H?E?E。廝錬劭味帖廚?E寨?E?

となりました。なんだかわかりませんね。 「・」は変換できなかった文字ですが、ここで文字境界がずれてしまっています。適当に1バイトの「ア」とかに置き換えてから変換してみます。

残念ながら現バージョケ裡廝?H?H筍臼映は
文??H修韻永おすことは出??H泙擦隠
2025年発売予定のW??H?H筍臼映は対吋します。
このト??H屮鰻ューティケ阿任蓮?
この??HΔ別簑蠅慮彊臼佑?泙瓠?
問題け??H垢臼?H烏します。
質問の答えけ?叡クしてください。
識腓暴召辰匿覆澆覆??H簑蠅臼?H任?泙后?

どうしますか?

仕淵がないか??H屮瀬ぅ▲?H阿罵靴椶Α廚閲猶?
「渡姫轡韻チのDeja??H臼。廝錬劭味帖廚閲猶?

さっきよりはマシになった気がします。

あとは、前後の文脈から判断して、文字を埋めて逆変換して元の画像の文字と合うかどうかを確認していくという地道な作業を行います。「現バージョケ」は恐らく「現バージョン」だろうとか、そういう感じで。

復元した結果がこれです。「〓」の部分はわかりませんでした。

残念ながら現バージョンのWindowsでは
文字化けをなおすことは出来ません。
2025年発売予定のWindowsでは対応します。
このトラブルシューティングでは、
このような問題の原因を突き止め、
問題を解決する手順を示します。
質問の答えをクリックしてください。
手順に従って進みながら問題を解決できます。

どうしますか?

仕方がないから「ダイアログで遊ぼう」を〓〓〓
「渡部シンイチのDejavu WORLD」を〓〓〓

内容が意味不明でちょっと怖いんですけど…。

[追記]

はてブのコメントで知ったのですが、どうやら元ネタは、「ダイアログで遊ぼう」というサイトに投稿されたネタ画像のようです。 「渡部シンイチのDeja=vu WORLD(デジャ=ヴ・ワールド)」で製作者のコメントを見ることができます。