M.C.P.C. (Mamesibori Creation Plus Communication)

印刷屋から五反田のWeb屋に転職したCLのブログです。

“人生相談テレビアニメーション「人生」”の組版がやばくて修羅場

今期日曜の東京MXの22時は“人生相談テレビアニメーション「人生」”ということで(見られない奴らはすまん、おれも2年前まで見られんかった)、主人公は第二新聞部に所属して理系代表・文系代表・体育系代表(そのうち美術系代表)の女子たちとお悩み相談投稿の答えをひりだすっつーシチュのラノベのアニメ化。

(第二新聞部とか杉並っぽいよな←D.C.脳) (現実の新聞部はこんなゆるくないのでやめておいたほうがよい)

その中で、新聞部なんでお悩み相談の回答が掲載された新聞を校内掲示板に貼り出していたわけですけれども、

私自身は新聞本文のプロポ組は18年前やってみたけど出来栄えがクズくてやめたのですが、その残念組版とここで再会。お久しぶりっす! 桂小金治の目にも涙!

私もクズいことを言うけれども組版スキルなければ一回ベタ組で流してみてからそこそこの版面設計して調整したほうが断然楽なのでみんな楽な方を選べばいーのにとか思います。

楽ってなんだよっていう話もあるけど、やっぱり組版経験だったりするのかな。広告系の方って本文も詰めたがるしなあ。

このブログエントリのタイトルに「修羅場」ってつけたのは、これって広告系デザイナーと書籍系デザイナーで意見の相違がみられるっぽいってこってす。どうするんだろうね。

人生 (ガガガ文庫)

人生 (ガガガ文庫)

↑まだ読んでないけど帰宅部っぽいのかな↓帰宅部連載終わてもうた

帰宅部活動記録(1) (ガンガンコミックスONLINE)

帰宅部活動記録(1) (ガンガンコミックスONLINE)

Raspberry Piでnode.jsをndenvでインストールする

Raspberry Pi(Raspbian wheezy)でPerl 5.20.0+AnyEventを使ってTwitterからのイベントに反応してタイムライン変更でPOP音出したりMS100A(BerryClip)のLED光らせたりICQのアッオー音だしたり誰かがツイ消ししたら汚らしい音が鳴ったりAquesTalkPiでツイート読みあげさせたりするうざいマシン(無駄にWi-Fiルータ電源供給で携帯できる)を作っていたんですがPerl 5.20.0のインストールだけで2時間はかかるので、どうしようかなーと思っていたんですけれども、Perl+AnyEventでプログラムを記述するのであれば、プログラムの形式が大体同じ形になるnode.jsでもいいんじゃないかなーと思いました。node.js本体インストールはバイナリを展開するのでものすごく速いし。

ローカルインストーラとして有名なndenvでインストールすると、アーキテクチャ名(armv6l)とパッケージ名(arm-pi)の齟齬があってインストールできなかったのですが、今日からはインストールできるはず。さっきGitHubでPull Requestをマージしていただきました。

$ git clone https://github.com/riywo/ndenv.git ~/.ndenv
$ mkdir ~/.ndenv/plugins
$ git clone https://github.com/riywo/node-build.git ~/.ndenv/plugins/node-build
$ cat << 'EOT' >> ~/.bash_profile
export PATH=$PATH:$HOME/.ndenv/bin
eval "$(ndenv init -)"
EOT
$ source ~/.bash_profile

ここまででRaspberry Piの現在ログインしているユーザでndenvが使えるようになる(いろんな兼ね合いでrootユーザで実行することになりそう)

$ ndenv install v0.10.26
$ ndenv global v0.10.26

http://nodejs.org/dist/v0.10.26/node-v0.10.26-linux-arm-pi.tar.gz をダウンロードして設置、グローバルで使えるようになります。Raspberry Pi用ファイルは現時点ではv0.10.26までにしか最新版が無いので注意

インストールはしたがまだスクリプトは書いていないので動作確認は

$ node -v
v0.10.26

で勘弁です

TwitterのAPIから得られる日付文字列をPerlのTime::PieceでParseする

Perlの日付を処理するモジュールはTime::PieceがいいよーなぜならばDateTimeは遅いから、ていう話なので、Twitter APIから出てくる日付文字列をTime::Pieceによるパースで一発処理する方法。strptime用のテンプレート表記するのがダサいなーとか思っていたけど、追加モジュール入れなくていいのは正義だよね。

use strict;
use warnings;
use Time::Piece;
my $tw = { created_at => "Sat Aug 01 01:56:26 +0000 2009", }; # Twitter APIの日付文字列
my $tp = localtime Time::Piece->strptime( $tw->{created_at}, "%a %b %d %T %z %Y")->epoch;
print $tp->datetime."\n"; # 2009-08-01T10:56:26 (ISO 8601)

タイムゾーンをうまく処理するためにいったんエポック起点のUNIX秒にしてlocaltimeにぶっこむ件は、 http://blog.dtpwiki.jp/dtp/2012/02/perldatetimetim.html で自分で書いてたやつを参照。

参考:過去に書いたPerlで日付をパースするモノたち

日付関連の処理は僕自身、過去にも結構やっていたみたい。

Twitter APIの日付文字列をDateTimeに食わせる

DateTime::Format::HTTPのパーサでDateTimeのオブジェクトにしちゃおうという案。しかし、DateTime::Format::HTTPは+0000形式の時差表記が理解できないので、GMTに無理やり置換することで対処。スマートではないよね。

TwitterのAPIから得られる日付文字列をPerlのDateTimeでParseする - M.C.P.C.

use strict;
use warnings;
use DateTime::Format::HTTP;
my $tw = { created_at => "Sat Aug 01 01:56:26 +0000 2009", }; # Twitter APIの日付文字列
(my $timestamp = $tw->{created_at}) =~ s|\+0000|GMT|;
  # DateTime::Format::HTTPは+0000形式のタイムゾーン認識しない
my $dt = DateTime::Format::HTTP
         -> parse_datetime( $timestamp ) # GMTタイムゾーン確定
         -> set_time_zone('local'); # 現地時間タイムゾーンへ変換
                                    # 'Asia/Tokyo'のほうが処理速い
         # http://diary.lampetty.net/20061206.html#p01
         # http://blog.livedoor.jp/dankogai/archives/50708234.html
print "$dt\n"; # 2009-08-01T10:56:26 (ISO 8601)

Twitter APIの日付文字列をDate::Parseに食わせてからDateTimeに食わせる

何がいいかっていうと、気持ち悪いタイムゾーン文字列の置換とか、気持ち悪いstrptime用テンプレート文字列とかが無いので気持ちがすっきりすることです。でもこれからはググってこのページを表示させて最初のやつ見て使うだろうからもういらないよね。

DateTime::Format::HTTPがPDTのタイムゾーンを食えなかったでござる - M.C.P.C.

use strict;
use warnings;
use DateTime;
use Date::Parse;
my $tw = { created_at => "Sat Aug 01 01:56:26 +0000 2009", }; # Twitter APIの日付文字列
my $epoch = str2time($tw->{created_at});
my $dt = DateTime->from_epoch( epoch => $epoch )
         -> set_time_zone('local'); # 現地時間タイムゾーンへ変換
                                    # 'Asia/Tokyo'のほうが処理速い
         # http://diary.lampetty.net/20061206.html#p01
         # http://blog.livedoor.jp/dankogai/archives/50708234.html
print "$dt\n"; # 2009-08-01T10:56:26 (ISO 8601)

JavaScriptのDate.parse()用日付文字列を生成するため、UNIX秒をDateTime::Format::Mailに食わせる

JavaScriptDate.parse()でパース出来る文字列っていうのはブラウザごとにまちまちっていう一部で有名な話があって、それに対応するためにPerl側でなるべくどのブラウザのJavaScriptでも処理できるような日付文字列を用意しようという作戦。

DateTime::Format::Mailを使うのだけれども、DateTimeベースだから重い遅いということになります。新規に組むのならDateTimeベースのものはあまり使わないほうがよい。

PerlからJavaScriptに日付を渡すのにMojo::Dateを使う - M.C.P.C.

use strict;
use warnings;
use Date::Parse;
use DateTime;
use DateTime::Format::Mail;
my $tw = { created_at => "Sat Aug 01 01:56:26 +0000 2009", }; # Twitter APIの日付文字列
my $epoch = str2time($tw->{created_at});
my $dt =
  DateTime::Format::Mail->format_datetime( 
    DateTime->from_epoch( epoch => $epoch )
  );
print "$dt\n"; # Sat, 01 Aug 2009 01:56:26 -0000

JavaScriptのDate.parse()用日付文字列を生成するため、UNIX秒をMojoliciousのMojo::Dateに食わせる

ひとつ前のを、Mojolicious組み込みのMojo::Dateでやってみる。Mojoliciousでサーバサイドを作る場合これでやる方法もあるのだけれども……

PerlからJavaScriptに日付を渡すのにMojo::Dateを使う - M.C.P.C.

use Mojo::Date;
use Date::Parse;
my $tw = { created_at => "Sat Aug 01 01:56:26 +0000 2009", }; # Twitter APIの日付文字列
my $epoch = str2time($tw->{created_at});
my $dt = Mojo::Date->new($epoch)->to_string;
print "$dt\n"; # Sat, 01 Aug 2009 01:56:26 GMT

JavaScriptに日付食わせるならUNIX秒で送ったほうが早い

ぎゃふん!

東京に来たら一度はやってみたい「エロゲーの背景の場所に行ってみる」

新潟から東京に引っ越して2年が過ぎようとしています。いま、五反田勤務なんで通勤の便がいいということで東急池上線沿線に住んでいるのですが、駅の形って鉄道会社ごとに雰囲気が決まるのね。そんなことを思いながらうちの近所を歩いていたら、なんだかこの駅見たことあるぞ、と思いました。

1996年のエロゲー「さくらの季節」(これはこれでどっかで見たことある感じの女の子がわんさか出てくる)の背景が、うちから2駅いったところの久が原駅にそっくりだったのでした。こういうことってあるのね。新潟や秋田だとこうはいかないとか思っていたけれども、新潟は今年になってからすーぱーそに子新潟駅万代口の高速バス乗り場とか、中条とか胎内に行っていて、たまげた。

f:id:C_L:20140614060615j:plain

そにアニ7話のここが新潟駅前の高速バス乗り場。20年前大学受験で初めて新潟に降り立った時、「駅前なのにイトーヨーカ堂がない!」と叫んでしまったぐらいかなり不愛想なビル街です。

そにアニ7話、「そに子君、どこ行ってもうたんや……」思ってたらどうして中条。

つうわけで、いつの間にか新潟でも聖地巡礼?できるようになってたというお話でした。

Illustrator用JavaScriptをJSLintとJSHintによる整形を参考にして修正する

http://www.iwashi.org/archives/2540:マシンを買い換えたくなってくる、DTP向けIllustratorベンチマークスクリプト - やもめも

(引用)

var start = new Date().getTime();
documents.add(DocumentColorSpace.RGB,3370,2284);
mColor = new RGBColor();
 
for (b = 0; b<16; b++)
{
mColor.red = b*14;
mColor.green = b*12;
mColor.blue = b*10;
for (i = 0; i<19266; i++)
{
a = Math.floor(i/114)
tObj = activeDocument.pathItems.rectangle(b+20+(i-a*114)*20,b+a*20,4,4);
tObj.filled = true;
tObj.stroked = false;
tObj.fillColor = mColor;
}
}
 
activeDocument.views[0].zoom = 0.1;
activeDocument.views[0].zoom = 2;
var end = new Date().getTime();
prompt("結果",end-start);

(引用終わり)

上記を、JSLintとJSHintの両方の指摘に合わせて修正するとこうなります。

var start = new Date().getTime();
documents.add(DocumentColorSpace.RGB, 3370, 2284);
var mColor = new RGBColor();

for (var b = 0; b < 16; b++) {
    mColor.red   = b * 14;
    mColor.green = b * 12;
    mColor.blue  = b * 10;
    for (var i = 0; i < 19266; i++) {
        var a = Math.floor(i / 114);
        var tObj = activeDocument.pathItems.rectangle(
            b + 20 + (i - a * 114) * 20,
            b + a * 20,
            4,
            4
        );
        tObj.filled    = true;
        tObj.stroked   = false;
        tObj.fillColor = mColor;
    }
}

activeDocument.views[0].zoom = 0.1;
activeDocument.views[0].zoom = 2;
var end = new Date().getTime();
prompt("結果", end - start);

プログラムの表記を整理しておくと、DTP屋さんとプログラム屋さんのコラボレーションが必要になった時、より意思疎通が図りやすくなります。

(昔は、「DTP屋がIT屋さんに置いていかれる」とか書いていたんだけれども、言っていた当時は「おまえは誰と戦っているのだ」と言われていたし、そう言いってた僕がDTP屋に居られなくなってしまいまるでギャグになったのでもう言わない)

ちなみに、ベンチマークについては、Pentium Dual-Core G3220で引用元のCore i7のスコア超えるみたいです。超省エネだし、Haswellってすごいね。

JavaScriptコーディング ベストプラクティス 高速かつ堅牢なコードを効率よく書くために

JavaScriptコーディング ベストプラクティス 高速かつ堅牢なコードを効率よく書くために

高度すぎる「改定新版 サーバ/インフラエンジニア養成読本 管理/監視編」

「改定新版 サーバ/インフラエンジニア養成読本 管理/監視編」という書籍が出ていたので購入しました。

(書影が蛍光グリーンになっていて実物と違うのだけれどもよいのか)

それを読んでいたわけですけれども、書いていることが高度すぎて、僕らの現場には合わない気がする。

2つほど引用して、われらが現場では実際に何が起こっていたかということを書いてみます。

p.110

トラブル2 まったくWebサーバへ接続できなくなった


問題察知 WebサーバにHTTPで接続できないというアラートメールがNagiosから届きました。実際にWebサービスにアクセスしてみましたが、やはり接続できない状態になっていました。


原因1 ネットワークが疎通していない

原因2 負荷が高い

【本当の原因】OOM KillerがApacheを殺していた ついでにsshdも殺されていた(ついでってなんだよ)

「OOM Killerなんて起こさせるなよ」

ごもっとも。でもここの運用はWebARENA時代からWebにアクセスできなくなったらコンパネからOpenVZのコンテナを再起動するっていうことになっていたっぽい。入社してまず最初にやったのは、ApacheのMaxClientsの数を減らすってことでした。MaxClientsを減らすだけでサーバダウンを防げて英雄になれる職場がそこにはある。

p.113

トラブル3 Webサーバを再起動したら、Webサーバにアクセスできなくなった


問題察知 Webサーバをメンテナンスしたときにカーネルをアップデートし、Webサーバの再起動が必要なので再起動しました。ところが、再起動後、Webサーバに全くアクセスできなくなってしまいました。具体的には、HTTPやSSHでWebサーバへ接続できなくなってしまいました。


原因1 カーネルのアップデートによる不具合

原因2 ネットワークが疎通していない

【本当の原因】httpd.conf を修正し損じていて、文法エラーで起動しない(この場合SSHは通るな)

service configtest しろよ」

ごもっとも。でも、ここの運用ではhttpd.confの書き換えはWebminで行うんだ。おーいこんそーるにおりてこいよーこわくないよー

(WebminはApacheを使わず自力でHTTPサーバを演じているので、ブラウザでWebminにアクセスできてApacheがダメな場合「Apacheがお亡くなりになられている」とわかって便利ではある)

~~~

この現場はいろいろ闇が深い。だからおもしろい。でももうかんべんしてくれ。(人の回転率が良すぎて育つ前にいなくなる)

※フィクションです

LANDISK HDL2-Aの専用フォーマットをLinuxで行いAFT HDD対応

LANDISK HDL2-Aという同型のHDDが2台入ったNASを使っております。NTT-Xで狂った安さだったので買ったやつです。

で、これをRAID 1にして使っているのですが、ご存知の通り、RAID 1であってもコントローラが壊れると結局データにアクセスできなくなるので、さらに別のHDDにコピーしておいた方がいいといわれていまして、この製品の場合も、USB HDDにFAT32もしくは専用フォーマットを施すことでコピー用の第三のストレージユニットが用意できます。

その第三のストレージユニット用に買ってきたHDDなのですけれども、今時のHDDはフォーマットが以前と違ってAFTなるものになっていて、何も考えずにフォーマットするとAFTに適合せずに遅くなるとなむ。何も考えずにフォーマットしてくれるモノの代表格としてWindows XP(63セクタースタート)とかあるのですが、このLANDISK HDL2-Aに至っては、この機械の専用フォーマットをすると1セクターからのスタートとなりまして、これもあかんやつでした。

というわけで、いろいろ調べたところ、LANDISK HDL2-Aの専用フォーマットなるものは、Linuxext3ファイルシステムで、ルート用の予約領域がない設定でありました。

以下は、LANDISK HDL2-Aの専用フォーマットしたものを再フォーマットしてみた感じのものです。最近のWindowsの流儀にあわせて2048セクタースタートにしました。使ったLinuxはXenServer 6.2です(察してください)。partedはCentOS 5のrepoから借用。

[root@xs01 ~]# parted /dev/sdc
GNU Parted 1.8.1
/dev/sdc を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) p                                                                

モデル: WDC WD20 EZRX-00D8PB0 (scsi)
ディスク /dev/sdc: 2000GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos

番号  開始    終了    サイズ  タイプ      ファイルシステム  フラグ
 1    0.51kB  2000GB  2000GB  プライマリ  ext3                    

(parted) u s                                                              
(parted) p                                                                

モデル: WDC WD20 EZRX-00D8PB0 (scsi)
ディスク /dev/sdc: 3907029167s
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos

番号  開始  終了         サイズ       タイプ      ファイルシステム  フラグ
 1    1s    3907029167s  3907029167s  プライマリ  ext3                    

(parted) rm 1
(parted) mkpart 
パーティションの種類?  primary/プライマリ/extended/拡張? p                
ファイルシステムの種類?  [ext2]?                                          
開始? 2048s
終了? 3907029167s                                                         
(parted) p                                                                

モデル: WDC WD20 EZRX-00D8PB0 (scsi)
ディスク /dev/sdc: 3907029167s
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos

番号  開始   終了         サイズ       タイプ      ファイルシステム  フラグ
 1    2048s  3907029167s  3907027120s  プライマリ                          

(parted) q                                                                
通知: 必要であれば /etc/fstab を更新するのを忘れないようにしてください。  

[root@xs01 ~]# mkfs.ext3 -m 0 /dev/sdc1
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
244203520 inodes, 488378390 blocks
0 blocks (0.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=0
14905 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
    102400000, 214990848

Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 20 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@xs01 ~]# mount /dev/sdc1 /mnt/
[root@xs01 ~]# ll -a /mnt
合計 24
drwxr-xr-x  3 root root  4096  3月 25 22:15 .
drwxr-xr-x 23 root root  4096  3月 25 01:27 ..
drwx------  2 root root 16384  3月 25 22:15 lost+found
[root@xs01 ~]# chown nobody:nobody /mnt
[root@xs01 ~]# ll -a /mnt
合計 24
drwxr-xr-x  3 nobody nobody  4096  3月 25 22:15 .
drwxr-xr-x 23 root   root    4096  3月 25 01:27 ..
drwx------  2 root   root   16384  3月 25 22:15 lost+found
[root@xs01 ~]# rm -rf /mnt/lost+found/
[root@xs01 ~]# ll -a /mnt
合計 8
drwxr-xr-x  2 nobody nobody 4096  3月 25 22:24 .
drwxr-xr-x 23 root   root   4096  3月 25 01:27 ..
[root@xs01 ~]# umount /mnt 

てな感じにしたHDDを、Linux機から取り外して、USB接続HDDケースなどでLANDISKに接続すると専用フォーマットされた外付けHDDと認識する。出たばかりのWD Caviar Greenとは違ってそんな神経質になる必要はないかもだけれども、Linux側でアライメント調整ができるっていう例でございました。

というか、このHDDとは別に、その出たばっかりの頃の2009年もののWD Caviar Green 1TB WD10EADSが、Linuxで使おうとするとすぐファイルシステムが壊れちゃうんですよ……