日記
案件Aが終わって、案件Bが中断して、みたいな感じで絶賛無職中。仕方ないので久々にお仕事探ししてる。
こんなところで募集しても意味ないと思うけど一応募集しとくと、フルリモートでやってる自営プログラマです。Perl, PHPがちょっとできます。別に言語にこだわりないし環境にこだわりないしやることにこだわりないので、合法的な仕事なら条件面で折り合えばなんでもやります。お仕事ください。
それはいいとして。
やることはあるけど暇っちゃ暇なんで、働き方の見直しなんかもしてて。去年後半くらいからかな? に、やれるだけやるみたいな働き方から、週の労働時間を20時間に固定する形に変更してみたんだけど、それでもまだ長いなあとか思うこともあって。
で、最近読んだ「シリコンバレー式 よい休息」って本の影響なんかもあって働き方をまたちょっと変えてみようと思った。この本タイトルはアレだけど割といい本なんで、みんな読もう。
新しい働き方は、午前と夕方に1時間半~2時間くらいを1回ずつ、あと午後に軽めの、主にメール対応など事務処理や、勉強に使う時間を1時間の、計4~5時間を1日に。
それを週4日くらい働く感じでどうかなー、とか。
いい感じだったら今度もっと詳しくブログに書くかも。
Linuxbrewに日本語のロケールを入れる
tmuxはデフォルトではUnicodeの曖昧な文字幅に対応していないので、パッチを入れるかあきらめるかで対処しなければならなかったのだが、最近はLinuxbrewというMacのHomebrew互換のパッケージマネージャ用にパッチ済みのtmuxの設定(Formula)を用意してくれている人がいるようだ。
最高なのでそれを使わせてもらおうとLinuxbrewを入れるところから始めたら、ロケール周りではまった。
tmuxは変なロケールで起動しようとすると、フォールバックなどせず以下のようなメッセージを出して落ちる。
tmux: invalid LC_ALL, LC_CTYPE or LANG
Linuxbrewで、こちらのFormulaを使ってtmuxを入れると、なぜかこの問題が起きる。試しにlocaleを実行して確認してみると、以下のような警告が出た。
locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_MESSAGES to default locale: No such file or directory locale: Cannot set LC_ALL to default locale: No such file or directory LANG=ja_JP.UTF-8 LC_CTYPE="ja_JP.UTF-8" LC_NUMERIC="ja_JP.UTF-8" LC_TIME="ja_JP.UTF-8" LC_COLLATE="ja_JP.UTF-8" LC_MONETARY="ja_JP.UTF-8" LC_MESSAGES="ja_JP.UTF-8" LC_PAPER="ja_JP.UTF-8" LC_NAME="ja_JP.UTF-8" LC_ADDRESS="ja_JP.UTF-8" LC_TELEPHONE="ja_JP.UTF-8" LC_MEASUREMENT="ja_JP.UTF-8" LC_IDENTIFICATION="ja_JP.UTF-8" LC_ALL=
結論から言うと、システムではja_JP.UTF-8が存在するが、Linuxbrewで入ったglibc周りでは存在しないということだった。
Linuxbrewでは、glibcが入るときにロケールを無視するらしい。詳しくはわからないのだが、どうもLinuxbrewは環境変数をフィルタリングするらしい。
以下のようにして、glibcインストール後のlocaledefなどの処理を再実行すると必要なロケールが入る。
HOMEBREW_NO_ENV_FILTERING=1 brew postinstall glibc
なおこの機能にはちょっとしたバグがあり、環境変数から雑にcharmap, localeの名前を取得しているため、ja_JP.utf8のような設定になっていると上記のコマンドがエラーになる。
この場合は、ロケールを再設定する。あるいは以下のようにlocaledefを手動で実行してもいいかもしれない。
localedef -i ja_JP -f UTF-8 ja_JP.utf8
ちなみに入れたパッチ済みtmuxはこちら。便利。あとLinuxbrewもバグったところ以外は便利な感じなので今後もいろいろ使ってみたい。
Test::DifferencesでUTF-8文字列をエスケープせずに出力する方法
ドキュメントに書いてある、 Text::Diff
の設定をどうこうする方法では駄目だったのでいろいろ調べた感じ、以下のようにすれば行けた。
use strict; use warnings; use utf8; use Data::Dumper; { package Data::Dumper; our $Useperl = 1; no warnings 'redefine'; sub qquote { shift; } } use Term::Encoding qw(term_encoding); use Test::More; { my $builder = Test::More->builder; my $term_encoding = term_encoding; binmode $builder->output, ":encoding($term_encoding)"; binmode $builder->failure_output, ":encoding($term_encoding)"; binmode $builder->todo_output, ":encoding($term_encoding)"; } use Text::Diff::Config; $Text::Diff::Config::Output_Unicode = 1; use Test::Differences; eq_or_diff 'あいうえお', 'かきくけこ'; done_testing;
Data::Dumperがまず問題
Test::Differences
では内部的に Data::Dumper
を使用しており、そこで確実にエスケープされてしまうので、まずはその対処をしなければならない。
これはまともな方法ではどうにもならないので、以下のページを参考に qquote()
をハックする方法で対処した。
Data::DumperでUTF-8フラグつき文字列をエスケープさせないようにするには - ku
Test::Moreの出力をなんとかしないと、 Wide character in print...
が出ます
これはいつものアレ。最近 Test::More
も中身が Test2
になったりしてるみたいでよくわからないが、まだこのやり方でとりあえず通用した。
Test::Moreでマルチバイト文字列を出力する可能性がある場合。 - 遠い叫び
Text::Diffの設定をなんとかする
$Text::Diff::Config::Output_Unicode
を真にするだけ。なおこの設定、table_diff
以外では不要なので、 unified_diff
とかを使う場合はなくてもよい。
Test::Differences使わない方がいいんじゃないか説
あまりちゃんとメンテされてない感じだし、使わなくて済むならそうした方がいいかも。今は似たようなのでもっといいのあるんじゃない?
use_okがprove -lで実行すると通るのにperl -Ilibで実行すると通らなかった話
use Test::More; use_ok 'Foo::Bar'; done_testing;
みたいなテストを実行するとき、まあ普通は prove -l
する。1アサートごとの結果を見たい場合も prove -lv
とかでいいんだけど、このときは忘れてて perl -Ilib
で実行した。
上のようなテストだと通るんだけど、今回下のようなテストになってて通らなかった。
use File::Basename qw(dirname); use Test::More; chdir dirname __FILE__; use_ok 'Foo::Bar'; done_testing;
こうして最低限のコードにするとわかりやすいんだけど、 'lib'
の指し示す先が変わってしまうので通らないわけだ。
ただそうなると、なぜ prove -l
では通るのか?
軽く App::Prove
を読んでみると、 'lib'
を絶対パスにして処理していたのでそのせいで chdir
の影響を受けなかったっぽい。
(当然 lib/Foo/Bar.pm
は存在し、かつ use
できる前提)
今日はたまたまそれほど解決にそれほど時間かからなかったからいいけど、勘でデバッグするのって駄目だよなあ。バグ見つけたらとにかく二分探索しつつ問題の最小化していかないと。そういう癖つけないと。
ansible-lintのルールに関するメモ
ansible-lintを使ってみているのだが、ルールの一部がよくわからなかったりしたので調べて簡単にまとめてみた。
- ANSIBLE0002: Trailing whitespace
- ANSIBLE0004: Git checkouts must contain explicit version
- ANSIBLE0005: Mercurial checkouts must contain explicit revision
- ANSIBLE0006: Using command rather than module
- ANSIBLE0007: Using command rather than an argument to e.g. file
- ANSIBLE0008: Deprecated sudo
- ANSIBLE0009: Octal file permissions must contain leading zero
- ANSIBLE0010: Package installs should not use latest
- ANSIBLE0011: All tasks should be named
- ANSIBLE0012: Commands should not change things if nothing needs doing
- ANSIBLE0013: Use shell only when shell functionality is required
- ANSIBLE0014: Environment variables don't work as part of command
- ANSIBLE0015: Using bare variables is deprecated
- ANSIBLE0016: Tasks that run when changed should likely be handlers
- ANSIBLE0017: become_user requires become to work as expected
- ANSIBLE0018: Deprecated always_run
ANSIBLE0002: Trailing whitespace
これはほんとそのまんま。いずれかの行の末尾に空白があれば警告が出る。
ANSIBLE0004: Git checkouts must contain explicit version
git
モジュールでversion
を指定しなかったり、HEAD
に指定したりすると警告が出る。
ANSIBLE0005: Mercurial checkouts must contain explicit revision
ANSIBLE0004のhg
版。revision
を指定しなかったり、default
に指定したりすると警告が出る。
ANSIBLE0006: Using command rather than module
git
, curl
, service
その他、Ansibleモジュールが使えるところでcommand
, shell
を直接叩いてると警告が出る。
ANSIBLE0007: Using command rather than an argument to e.g. file
chmod
, mkdir
, rm
その他、file
モジュールの引数でできることでcommand
, shell
を直接叩いていると警告が出る。
ANSIBLE0008: Deprecated sudo
become
, become_user
でなくsudo
, sudo_user
を使っていると警告が出る。
ANSIBLE0009: Octal file permissions must contain leading zero
file
モジュールなどでmode
の指定時に0666
のような表記ではなく666
のような表記をしていると警告が出る。
ANSIBLE0010: Package installs should not use latest
ANSIBLE0004のパッケージ管理システム版。state
にlatest
を指定していると警告が出る。ANSIBLE0004などでは未指定の場合も警告が出るが、yum
などのstate
はデフォルトがlatest
ではなくpresent
なので、未指定の場合は警告が出ない。
ANSIBLE0011: All tasks should be named
すべてのタスクにname
をつけろというルール。そこは問題ないのだがこのルールバグってて、yum
のように引数にname
があるものだと、偽陰性になってしまう……。
ANSIBLE0012: Commands should not change things if nothing needs doing
command
, shell
などがwhen
, creates
などで条件つき実行になっていない場合警告される。
ANSIBLE0013: Use shell only when shell functionality is required
パイプやリダイレクトなどを使うわけでもないのにshell
を使ってると警告される。
ANSIBLE0014: Environment variables don't work as part of command
command
, shell
のコマンド内でPATH+=XXX command
みたいなのはできないよ、という警告だと思うのだが自信がない……。
ANSIBLE0015: Using bare variables is deprecated
{{ var }}
形式じゃない生の変数を使った場合に警告される。この「生の変数」を俺はそもそも知らなかったんだが、以下みたいな感じらしい。
--- - tasks: - name: example for "Using bare variables is deprecated" rule yum: name: item with_items: items
ANSIBLE0016: Tasks that run when changed should likely be handlers
when: result.changed
みたいなことやるなら普通にhandlers
使えば変更あった場合のタスク実行できるからそうしよう、みたいなルール。
ANSIBLE0017: become_user requires become to work as expected
become
なしでbecome_user
してると警告される。
ANSIBLE0018: Deprecated always_run
always_run
を使っていると警告される。check_mode
が代替とのこと。
Nginxでtypesは上書きできるのか
nginx実践入門をちまちま進めている。今日は第3章を進めていたのだが、いくつか気になることがあったので検証してみた。
typesディレクティブの設定値は上書きできるか?
実践入門には、基本mime.types
をinclude
して、別途指定したい場合はmime.types
を直接修正する、みたいな感じで書いてあった。
個人的にはそういうのはmime.types
はそのままにしておいて、必要なものだけ上書きする形でできたらいいなあと思ったので、できないのか試してみた。
# ... http { include mime.types; types { text/html txt; } } # ...
結果、Nginxを起動した時点で以下の警告が出た。その上で上書きはされるようだ。うーん、その仕様はどうなのか……。
2018/04/19 11:27:35 [warn] 1833#1833: duplicate extension "txt", content type: "text/html", previous content type: "text/plain" in ./etc/nginx.conf:17
ググったところ、以下のようにする感じでハックできると出てきた。
# ... http { include mime.types; server { # ... location ~ \.txt$ { types { text/html txt; } } } } # ...
https://serverfault.com/questions/678673/nginx-how-to-override-add-single-mime-type
その後調べると、公式リファレンスにもあった。上記のとは違い、types
は空にして、default_type
を使ってる。
http://nginx.org/en/docs/http/ngx_http_core_module.html#types
これはこれで微妙……。
access_logは複数設定するとどうなるのか?
access_log
を同じように複数設定した場合の挙動が気になったのでこれも一応確認してみた。予想通り、複数のファイルにアクセスログを出力してくれる。便利。
複数回同じディレクティブを書いた場合の挙動もちゃんと公式リファレンスに書かれてるとよかったんだが。
Nginxの技術書どれがよさそうか、中身を比較した上で買ってきた
動機
Nginx関係で知りたいことがあったんだけど、公式リファレンスだけだと十分詳しく載ってなかった。軽くググった感じでもなかった。英語の記事とかまで探す範囲を広げたらありそうだったけど、それも大変なので一冊本を買おうかなと。
Amazonのレビュー見たり、目次見たりしたけどどれがよさそうがなんとも言えない感じだったので、物理本屋に行って比較検討・購入してきた。
検討した本
比較検討したのは以下の4冊。古い順。
- マスタリングNginx (2013)
- Nginxポケットリファレンス (2015)
- nginx実践入門 (2016)
- nginx実践ガイド (2017)
Amazonでググった感じ、日本語の本ではほかに「ハイパフォーマンスHTTPサーバ Nginx入門」というのがあるらしかったが今日行った本屋にはなかった。見た感じ絶版っぽい。マスタリングNginxよりさらに古く2011年の本のようなので致し方なしか。
比較方法
あまり長々チェックするのもいろいろアレなんで、前書きその他をざっと見て感じをつかんだ上で、知りたかったことの一部、proxy_buffering周りについてどう書かれているかをそれぞれの本でチェックした。
詳しく書かれている順に、
- マスタリングNginx. 設定値による挙動の変更がかなり具体的に書かれていた。
- nginx実践入門。マスタリングNginxほどではないものの、十分に詳しく書かれていた。
- Nginxポケットリファレンス。1, 2と比べるとだいぶ不足しているが、一応目安となる設定値は書かれていた。
- nginx実践ガイド。ほぼ公式リファレンスと同等のことしか書かれていなかった。また、索引にproxy_bufferingがなぜか載っていなかった。
なお実際に買った本以外は記憶ベースで書いてるんで、おかしいところとかあるかも。
購入した本
迷ったが最終的にnginx実践入門を購入した。
内容的にはマスタリングNginxがよさそうだったが、nginx実践入門もだいぶよさそう。かつ実践入門は、
- ちょっと安い。300円くらい?
- ちょっと新しい。3年くらい。
あたりがあったので。もし物足りなかったらマスタリングNginxを追加で買うかもしれないが、まあWebサーバとかそこまで自分でどうこうしないので、どうかな。
やっぱりリアル書店は比較検討しやすいのがいい。ただ、できれば電子書籍で買いたかった。店頭で普通に電子書籍も置いてくれると助かるのだが。