Git/Mercurialを使いデスクトップとラップトップで作業する

GitやMercurialでの分散作業というのは、高度なユーザーやギークばかりでなく、多くの人にとってメリットのある手法だ。 デスクトップを母艦としてラップトップを使う人にとっては確実に意味のあることだろう。

基本的な話

まずいまいちど基本的な手法を確認しよう。 まず、基本となるリポジトリを作る。

Gitの場合

$ cd ~/Repositories/Myrepo.git
$ git init --bare
$ cd ~/Work
$ git clone ~/Repositories/Myrepo.git

Mercurialの場合yvarn

この違いは、Gitがワーキングツリーを持つリポジトリに対する同期を非推奨としていることによる。 そのため、同期するためにはベアリポジトリを作り、その上でワーキングリポジトリとしてcloneする必要があるのだ。

Mercurialの場合は特にそのような必要はなく、ワーキングツリーを持つリポジトリをcloneすれば分散作業できる。

ここでは話を楽にするためにMercurialを使おう。

デスクトップコンピュータのdragon.localホストの~/Work/Wyvarnリポジトリを作ったとする。 この作業を外で続けたくなったので、ラップトップ(knight.local)でこのリポジトリをcloneする。

$ cd ~/Work
$ hg clone ssh://jrh@dragon.local/Work/Wyvarn

Mercurialのsshアクセスはパス部が相対パスで始まっているものとみなすので注意してほしい。絶対パスで指定するためにはパス部を/ではじめる必要がある。

過酷な作業を終え、充実の成果をあげた。では家に帰ってその成果を反映しよう。

$ cd ~/Work/Wyvarn
$ hg push

続きはデスクトップで。デスクトップでリポジトリのアップデートを反映する。

$ cd ~/Work/Wyvarn
$ hg update

変更に強い構成にする

だが、実のところこのようなシステムではファイルの配置が変わったり、ファイル名が変わったり、ホスト名が変わったりするのはよくあることだ。 そのたびにすべてのリポジトリを修正するのはかなりの手間がかかる。

これにはふたつの抽象化レイヤーの導入が有効だ。

まずは、ホスト名を、そのホストに依存したものではなく、専用の固定名を与える。 ホストが少ないのであれば/etc/hostsファイルで良いだろう。

192.168.2.100          repo

多いのであれば、dnsmasqを使うと良い。

続いてリポジトリへのパスを抽象化しよう。 これは、次のようにするといい。

# mount --bind ~jrh/Repositories /mnt/repo

その上で

/home/jrh/Work/Wyvarn -> /home/jrh/Repositories/Wyvarn

のような状態にしておけばいいだろう(実体の位置を間違えないように)。

そして、ラップトップでは

$ hg clone ssh://jrh@repo//mnt/repo/Wyvarn

のようにすればいい。

Linux Tips

YouTubeのプレイリストからタイトルを抽出する

結局使わなかったのだが、ワンライナーで書いた。 比較的素直なHTMLなので解析は簡単。行指向ではないので、PerlでなくRubyにした。

$ curl 'https://www.youtube.com/playlist?list=<playlistid>' | ruby -e "s = STDIN.read" -e 's.scan(/<a class="[^"]*pl-video-title-link[^"]*"[^>]*>(.*?)</m) {puts $1.strip }' | grep -v 動画は削除されました

ffmpegでh.264/aacな360pのmp4を

元動画は1080pのmovまたはmp4。 オーディオはいじらず、元々aac(ac3)。

$ ffmpeg -i <infile> -vcodec libx264 -s 640x360 -crf 34 -strict -2 <outfile>.mp4

ちなみに480p(16:9)は720×280。 -crfの値は18-28が推奨されている(小さいほど高ビットレート)が、今回はモバイル向けなので34を指定。

なお、6の増減でビットレートはおよそ1:2の変動となる。

ffmpegでCowon M2向けの動画を作る

COWON M2はXVidとmp3のAVI動画で、解像度は320×240またはWMVをサポートするとある。

WMVだと結構サイズが大きいので、AVIで作る。 ソースは前回と同じくh.264*ac3のMOVまたはh.264*m4aのmp4。

$ ffmpeg -i <infile> -vcodec libxvid -acodec libmp3lame -b:v 372k -b:a 128k -s 320x240 <outfile>.avi

随分としょぼい解像度の上にアスペクト比も壊れる(プレイヤー側で調整することは可能)が、案外見られる。 ただし、360pでも細部は潰れてしまっているのでよく分からない部分は出てしまう。

XineのUIの文字化けを直す

fontにHerveticaを要求しているので、フォントエイリアスを設定すれば良い。

某コンテストの投票方式の問題点

先日まで某サイトでwebコンテストが実施されていた。だが、これにかなりの技術的問題点があったので、言及しておく。

会員に対する投票と、一般の投票は、票の重さが違う、という仕様で、一般投票は1日に1票、ということだった。しかし、この重複票排除というのは、現実にはまず不可能である、とされている。

重複票排除については1995年頃から議論されていた。1人1票、と設定しても、どうやってその人が既に投票したかを確認するか?ということだ。方法としては、IP, IP+UA, Cookie, 登録制が一般的だった。

IPはゲートウェイホストによって個々のインターネットホストに与えられるため、同一IPの投票を重複とみなす、という方式だ。だが、この方式は、インターネットカフェやケータイ(これは2000年以降)で問題が生じることと、NATを用いるために同一世帯の家族を「重複票とみなしてしまう」という問題があった。一方、PPPならば「電話をかけ直す」ことでIPアドレスは振られ直すことが多く、この重複を排除できない。

IP+UAは、IPとUAの両方が一致する場合重複とみなす、というもので、会社、ネットカフェなど共有回線がまるごと重複とみなされる問題を回避しようとした。しかし、UAは当時は特にバリエーションがそれほど多くなかった上に、詐称することも可能だったため、会社などそれなりの規模になるとかなりの確率で、環境を揃えているネカフェではほぼ確実に重複とみなされ、一方重複投票したい人は容易に回避できた。

Cookie方式はブラウザに「投票した」という情報をもたせることで管理しようというものだ。比較的単純で効果があったが、手元に複数の、Cookieを共有しないブラウザがあれば回避されてしまうし、単にCookieを削除するだけでいくらでも投票できてしまう。

登録制は、重複登録をいかにして防ぐかが問題となる。また、登録制にすることでハードルが上がり、投票数は劇的に低下する。重複票を防ぐ効果は低く、それでいてむしろ避けられることになるため、よほど自信のある(中身にというよりも、popularityにおいて)プロバイダでなければ採用は逆効果だった。

これらの問題の難しさを諦めて、逆手にとったのがAKB方式といえる。つまり、重複投票はしても構わないが、その票数は買わなければならない口数方式だ。

例えば住基カードを使えば1人1票は実現可能だが、厳密性を求めるならなりすましの対策という非常に困難な問題にぶつかることになる。それに、選挙でもなければ同定に住基カードなど使えない。

携帯電話に限る、という方式はお手軽であり、普及している。電話番号を使うことで同定できるためだ。だが、そのような理由でコンテンツを携帯電話に限ることは、アクセシビリティの観点から言っても好ましくないし、やはりアクセスはかなり減少する。それに、そのような目的で電話番号を取得するのはいかがなものか?ということもある。

このほか、TwitterやFacebook, Google+のようなopenIDを使って認証する、という方式もある。電話番号よりはいくらかソフトなやり方だが、その分効果は低下する。

このように非常に難しい重複投票の制限だが、そのコンテストでは、単純にCookieを使う方式だった。CSRF対策か、セッションクッキーを使うようになっていたが、その場合、単純にブラウザのプライベートウィンドウを開いてアクセスし、投票して閉じれば無限投票が可能だ。

もっとあげつないやり方としては、curlなどでセッションクッキーを保存するようにして投票ページを取得したあと、投票するという2回のコネクションを張るだけで投票できる。この間0.1-3.0sec程度なので(私の環境で)、ループすれば1時間で1500票は入れられる。

これはさすがに中止になるか無効になるかするように思う。

もう少し考えて作ってもよかったのではないだろうか。

現在のシステムについて

私のコンピュータシステムについて質問があったのでまとめておく。

とはいえ、Linuxのシステムは全て説明するのは困難なので、概要に留める。

ハードウェア

ASRock FM2+Killer Extreame, AMD A10 7700K, 32GB RAM, 128GB SSD, 3TB HDDx5というのが主な構成。

外付けマルチドライブ、Canon MP630とEPSON GT-S630がある。プリンタ、スキャナはWindowsからは使用していない。

AUDIO I/OはAUDIO 4 DJ(セレクター経由でBOSE)、TASCAM US-366+FOSTEX AP05+VAIO付属スピーカー、アナログ出力のlogicool。US-366はLinuxでは扱えない。通常はClassic Proのヘッドフォン、製作時やリスニングではULTRASONE HFI-580を使用。

キーボードはオウルテックのメカニカルキーボード(青軸)、マウスはサンワサプライのBLUE-TECH有線、マウスパッドはELECOMの滑マウスパッド(大)。ELECOMのゲルハンドリストを使用。

机がL字型の自作となっている。

モニターは21.5インチのFullHDデュアル

システム

ディスクは以下のようになっている。

disk0(SSD)
Linuxシステム(/boot, /, /swap)
disk1,2,3,5
Btrfsボリューム
disk4
Windowsシステム(NTFS/UEFI)

Btrfsボリュームは2レッグミラー(RAID1+0相当)で運用される。サブボリュームを用いた運用で、サブボリュームの直下がEncfsディレクトリとなっており、~/.share.encfsにマウントされる。これをencfsで~/shareにマウントして使用する。

そもそもホームディレクトリの主要なディレクトリやファイルはシンボリックリンクとなっており、これをマウントしないとシステムをまともに使用することができない。システム自体もLUKSで暗号化されており、オフライン攻撃に対する強度を確保する。

Manjaro/WindowsともにUEFIでブートされる。ディスクは全てGPTとなっている。

Linux

ディストリビューション
Manjaro Linux JPを使用。0.8.10からのローリングアップグレード。
カーネル周り

Manjaro kernel 3.17を使用。AMD Catalystドライバで、オーバースキャンの設定をしてある。

ただし、この状態ではデスクトップ環境を問わず、HDMIモニター(セカンダリー)のカーソルがやがてバグる。

デスクトップ環境

XFce, Awesome, KDE, Cinnamonを用意。通常はKDEを使用。

KDEについてはSuper+Leftでウィンドウを左に寄せる、などエッジリサイズオプションを設定してある。

Conkyを使用しているが、KDEではRSSがうまく領域を確保されないことが多いので、あまり使っていない。

日本語環境

fcitx+Mozc-UT。

fontsは、Archで用意されている日本語フォントはだいたい入っている。

インターネット

ウェブブラウザはFirefox latest(binから入れたもの。スクリプト起動)とMaxthon, opera developerを使用。

メールはMaildeliver(自作スクリプト)でチェック、振り分け、フィルタリング、通知などを行い、Claws Mailで読む/出す。通知はデフォルトの通り、SOXとNotify Sendを使用。

TwitterはMikutter(Git)を使用。2chはJD(AUR)を使用。

その他、Skype+Sype Call Recorderを使用。

マルチメディア

半自動でCDをflacとOgg Vorbisに取り込むようになっており、Amarokで音楽コレクションを再生。

PDAPにはスクリプトを用いてOgg Vorbisを転送。Ogg VorbisはV192kbps。

ビデオはVLC/SMPlayer。

音声についてはPulseAudio経由で、出力デバイスはアナログオーディオ、HDMI、そしてNI AUDIO4 DJがあるが、設定によりAUDIO 4DJから音楽のみ出すようにしている。これはPulseAudioで設定してある。現在、Audio 4 DJから鳴るのはAmarokとSMPlyer。

画像は通常はGwenviewだが、Thunar+ViwniorやRistrettoも使用。

画像は投稿時などの変換はImageMagick。その他、GIMPとInkscape。

開発

PDocはmedit、コードはKate、プレーンテキストはTeaを使用。

バージョン管理はGitで、サイトのテキストもGitで管理、大部分はリモートGitを使用している。

リモートGitはCodebreak;, GitHubが主。

開発言語はRubyとZsh

シェル
XFce4 TerminalとZshを使用。Zshはmomongaをベースに拡張したrcで使用している。EXTENDED_GLOBは常にON。

Windows

デスクトップ

外観はU-7imate Final Version for Windows7, MacType, tronnixカーソルテーマを使用。

ランチャーはLaunchy。Rain Meterも控えめに使用。フォントは源柔フォント, 源真フォント, Rounded M+, Noto Sans Japanese, Ricty。

ユーティリティ
  • GeekUninstall
  • PeaZip
ファイラ
  • As/R
  • Hina File Master
日本語入力環境
Google日本語入力
マルチメディア
XnView
音楽制作環境
  • SONAR X3 PRODUCER
  • FL STUDIO Signature Bundle
  • KOMPLETE 9 ULTIMATE
  • Cabuse 6 LE
インターネット
ウェブブラウザ
  • Cyberfox AMD64bit
  • Sleipnir
メール
Oepra Mail
エディタ
  • Uneditor
  • VXEditor
セキュリティ
  • ZoneAlarm Free Firewall
  • Avast! AntiVirus Free

音楽制作環境なので、基本的に余計なものは入れないようにしている。

Windowsでウェブブラウジングを楽しむようなことはない。メールもメインアカウントのIMAPアクセスだけだ。だが、ブラウザは調べ物したりSoundCloudにアクセスしたりで必要となる。

パフォーマンス

Linuxでの並列作業や、WindowsでのDTMで使われているこのコンピュータのパフォーマンスについて述べる。

Linuxにおいて10000プロセスをforkして行う作業は、ほぼ問題ない。が、GUIはフリーズしたり、ひどい遅延を起こす。どちらかというと、fork時が問題になるようだ。ちなみに、Nepomukでシステムが使えなくなるまでには26万プロセスがforkされていたと記憶している。

おおよそ並列作業のために見境なくforkしても問題にはなりにくい。ただし、gccなどでは、やはり多くても12スレッドがいいようだ。並列性は、残念ながらあまり高くない。やはりこの作業ではコア数が必要となるので、FX-8が欲しいな、と思う。

全体にはCPUがボトルネックになっている。システムはSSDからロードされているため、ストレージ性能はそれなりにある。ネットワークもGbEでそれなりの帯域がある。RAMはKDEでも2GBもあればロードできるため、実際は8GBを越えることは稀だ。

しかし、ソフトの起動時に待たされる、特にKDEの起動が遅いことについては、やはりCPUがひっかかっているようだ。これはGIMPやLibreOfficeの待ち時間についても同様。KDEでもひっかかりが生じることがあり、明確にどこでということは読めないのだが、どうもCPUらしい。KDEは明らかにXFceのようにはさくさく動かない。リソースに常に余裕があれば、体感的な速度にはそれほど差がでないはずなので、常にではないが動きが悪いと感じるということはKDEに対して余裕がないのだろう。

ちなみに、パイプでのXZなどCPU中心となるものに関しても結構遅いと感じられる。コンパイルも意外と待つ。「すごく速い!」という印象はない。

IOスピードは、まぁ、この程度だろう。RAMも十分なのだが、それでももう少しあると快適になるシーンというのはある。バッファで使いきってしまうことは結構あるので、その時にはもっとメモリーがあればIO待ちの時間が減る。また、tmpfsに置けるファイルも増えるだろう。とはいえ、64GB化はエクスペリエンスの向上は乏しいだろう。

WindowsのDTMにおいては、ストレージスピード、RAM共に完全に余裕である。ストレージスピードが足りないようならば、ネットワークストレージのRAID0でさらなる高速化を準備していたが、その必要はなかった。

RAMは、Windowsでは逼迫したことがない。WindowsはRAMの使い方が下手だ、ということもあるが。

16トラックのシンセに20本のプラグインエフェクトを入れてもRAMには十分な余裕があったが、問題はCPUだ。上限に張り付くようなことはないのだが、US-366でlowest latencyにしていると、3トラック目あたりからノイズが乗ってくる。DTM作業をストレスなく行うには、かなりパワーが足りない印象だ。

AMP A APUは、クロック周波数がブースト時のものになっているので、その最大周波数で動いてくれるわけではない、というのが結構痛い。見ていると、ひとつのコアが60%くらいになるとノイズが乗り始める。この場合、他のコアは40%程度の使用率となっている。

Highest latencyにしてもノイズが除去できないこともある。結局、モアCPUパワー!な状態だ。

音楽制作においては、比較的低レベルでの動作が多いためか、どうもハードウェア的にインテルのほうがいいことが多いように思う。性能は同じでも、うまく動いてくれる気がする。一方、LinuxではFX 8がとても気になる。

現状、DTMではコアよりパワー、一方Linuxではパワーよりコアである感じがするのだが、まぁこれだけCPUの話ばかりになってしまうほど、CPUが遅い!

ちなみに、CPUについでパワーが足りないのは、ゲームなどしていないにもかかわらず、グラフィックだったりする。Windowsではもたつくというほどではないが、それでもYouTubeなどでは「んっ」と思う時がある。デュアルディスプレイの負荷が厳しいのかもしれないが、安定性も足りなかったりする。Windowsでもだ。

一応、この構成でもFHDx2+4kが可能なようではあるが、相当もっさりしそうだ。

クリエイティブな環境のためには、もっとCPUとGPUが必要だ、という結論に達した。

なおストレージ容量だが、現在はだいたい1.3TB。一時2.7TBまで行っていた。ネットワークが50Mbps程度しか出ていない(しかも、down率が10%を越える)ので増加は抑えめだが、本来限界まで簡単に行くとは思う。btrfsでいくらでもふやせるのはいいのだが、バックアップが難しくなっていくのは難点である。

画像PDFに黒塗りを入れる

ドキュメントスキャナで作成したPDFファイルのドキュメント、公開したいが一部データは個人情報であり公開できない…

そんなようなケースに私は遭遇した。まずは単純にPDFエディタを試そうとしたのだが、それはうまく動かなかった。LibreOfficeでもだ。

となれば、「一度画像にバラす」というのが無難な方法だろう。imagemagickでバラすことができる。

$ convert something-pdf-file.pdf out.png

シンプルな話だが、実際にできあがったPNGファイルをみてみるとガタガタで品質はかなりひどい。どうやらxpdf/popperを使ったほうがよさそうだ。

$ pdftoppm something-odf-file.pdf out.ppm

これでppmファイルで出来上がる。ppmファイルはgimpで編集できるので、gimpを使って編集すれば良い。pdftoppmを使って変換した場合、ImageMagickと比べるとかなり品質は良い。そして再編する。

$ convert out*.ppm out.pdf

ここではImageMagickを使う。これによる品質劣化はなさそう?だ。

ちなみに、ImageMagickを使ってppmをjpegにすることはできるが、品質オプションなしだとjpegから再編すると容量は123%程度に膨らんだ(PPM=26MB, JPG=32MB)。-quality 30まで落として再編すると、6MBまで落ちた。品質は、今回は便箋に書かれた文字であるため、このレベルなら問題ないだろう。サイズ縮小においても効果のある手法だ。-quality 15ではかなり荒れるが、それでも可読性に問題はない。このバージョンに差し替える予定でいる。ちなみに、2ページのデータはもともと2.4MBのPDFファイルだが、208kBまでの縮小に成功した。

このような場合、mogrifyを使ったほうがてっとりばやい。これはglobを使って一気に変換することを可能にする。例えばmogrify -format jpg -quality 15 *.ppmのようにだ。出力ファイル名を指定しても構わない。その場合、拡張子の前に連番が入る。

mount namespace, VineSeed, nc chat&ZeroMQ

mount namespace

試してみたのだが、うまくいかなかった。

通常は共有されるマウントツリーの空間だが、これをプロセス固有のものにすることができるのがmount namespaceだ。

mount namespace適用の方法はunshare –mount commandとなる。これでcommandが新たにマウントしたファイルシステムは、そのプロセスと子孫プロセスに固有のものになり、上流には反映されないという。

というわけで試してみた。

$ sudo unshare zsh
$ sudo mount -o subvol=testvol /dev/sdd2 /mnt/3
}

p {[
"しかし、異なるmount namespaceをもっているプロセスからもそれが見えてしまう。違うファイルシステムツリーをもっている環境を作りたかったのだが、それ以前の問題だ。",
"btrfs
]}

h3 "VineSeed"
p {[
"Vine Projectのお手伝いをすることにして、Seed環境を構築しようとしたのだが、マニュアルに従ってVirtualBox上で構築するも、うまくいかなかった。",
"ベースシステムで手順どおりにするとPlymouthのあとブラックアウト、フルインストールからではXDMが起動し、ログインしてもただちにXDMに戻る。",
"問題はVineSeed MLにレポート済み"
]}

h3 "ncでchat & ZeroMQで拡張を目論見る"
p {[
"LAN内のコンピュータととりあえずメッセージをやりとりするのに良い手段…と考えたのだが、なかなか良い方法がなかった。",
"最も手間がないのは、ssh+ncを使う方法だろう。",
"2つのコンピュータは、まず片方でつぎのようにして、コネクションを対話的に待ち受ける。",
]}

sb(c:"shell") { "$ nc -l 55555" }

p {[
"そしてもう片方のクライアントはSSHでログインし、ncで接続する。"
]}

sb(c:"shell) { <<-END
$ ssh -x user@host
$ nc localhost 55555

ふたりなら十分に実用になるが、頻繁に書いていると画面がごちゃごちゃになり、また消すことができない(日本語の場合)のも難点。

こういうのを処理するのがlibChat ZMQ Framework(私の作品)なのだが、そのベースになるようなシンプルなサーバーを書いてみた。

のはいいのだが、MageiaでRuby ZeroMQバインディングがインストールできない。Pythonのほうは用意されているのだが、

Building native extensions. This could take a while…
ERROR: Error installing zmq:
ERROR: Failed to build gem native extension.

/usr/bin/ruby extconf.rb
checking for zmq.h… yes
checking for zmq_init() in -lzmq… yes
Cool, I found your zmq install…
creating Makefile

make “DESTDIR=”
gcc -I. -I/usr/include/x86_64-linux -I/usr/include/ruby/backward -I/usr/include -I. -DHAVE_ZMQ_H -fPIC -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector –param=ssp-buffer-size=4 -fPIC -fPIC -o rbzmq.o -c rbzmq.c
rbzmq.c: 関数 ‘internal_select’ 内:
rbzmq.c:324:9: 警告: ‘rb_thread_blocking_region’ は廃止されました (宣言位置 /usr/include/ruby/intern.h:839) [-Wdeprecated-declarations]
rb_thread_blocking_region (zmq_poll_blocking, (void*)&poll_args, NULL, NULL);
^
rbzmq.c: 関数 ‘socket_getsockopt’ 内:
rbzmq.c:968:7: エラー: ‘ZMQ_RECOVERY_IVL_MSEC’ が宣言されていません (この関数内での最初の使用)
case ZMQ_RECOVERY_IVL_MSEC:
^
rbzmq.c:968:7: 備考: 未宣言の識別子は出現した各関数内で一回のみ報告されます
rbzmq.c:990:10: エラー: ‘ZMQ_HWM’ が宣言されていません (この関数内での最初の使用)
case ZMQ_HWM:
^
rbzmq.c:991:10: エラー: ‘ZMQ_SWAP’ が宣言されていません (この関数内での最初の使用)
case ZMQ_SWAP:
^
rbzmq.c:995:10: エラー: ‘ZMQ_MCAST_LOOP’ が宣言されていません (この関数内での最初の使用)
case ZMQ_MCAST_LOOP:
^
rbzmq.c: 関数 ‘socket_setsockopt’ 内:
rbzmq.c:1292:10: エラー: ‘ZMQ_HWM’ が宣言されていません (この関数内での最初の使用)
case ZMQ_HWM:
^
rbzmq.c:1293:10: エラー: ‘ZMQ_SWAP’ が宣言されていません (この関数内での最初の使用)
case ZMQ_SWAP:
^
rbzmq.c:1297:10: エラー: ‘ZMQ_MCAST_LOOP’ が宣言されていません (この関数内での最初の使用)
case ZMQ_MCAST_LOOP:
^
rbzmq.c:1315:10: エラー: ‘ZMQ_RECOVERY_IVL_MSEC’ が宣言されていません (この関数内での最初の使用)
case ZMQ_RECOVERY_IVL_MSEC:
^
rbzmq.c: 関数 ‘zmq_send_blocking’ 内:
rbzmq.c:1443:5: エラー: 関数 ‘zmq_send’ へ渡す引数が少なすぎます
send_args->rc = zmq_send(send_args->socket, send_args->msg, send_args->flags);
^
In file included from rbzmq.c:28:0:
/usr/include/zmq.h:349:16: 備考: ここで宣言されています
ZMQ_EXPORT int zmq_send (void *s, const void *buf, size_t len, int flags);
^
rbzmq.c: 関数 ‘socket_send’ 内:
rbzmq.c:1512:9: 警告: ‘rb_thread_blocking_region’ は廃止されました (宣言位置 /usr/include/ruby/intern.h:839) [-Wdeprecated-declarations]
rb_thread_blocking_region (zmq_send_blocking, (void*) &send_args, NULL, NULL);
^
rbzmq.c:1517:9: エラー: 関数 ‘zmq_send’ へ渡す引数が少なすぎます
rc = zmq_send (s, &msg, flags);
^
In file included from rbzmq.c:28:0:
/usr/include/zmq.h:349:16: 備考: ここで宣言されています
ZMQ_EXPORT int zmq_send (void *s, const void *buf, size_t len, int flags);
^
rbzmq.c: 関数 ‘zmq_recv_blocking’ 内:
rbzmq.c:1541:5: エラー: 関数 ‘zmq_recv’ へ渡す引数が少なすぎます
recv_args->rc = zmq_recv(recv_args->socket, recv_args->msg, recv_args->flags);
^
In file included from rbzmq.c:28:0:
/usr/include/zmq.h:350:16: 備考: ここで宣言されています
ZMQ_EXPORT int zmq_recv (void *s, void *buf, size_t len, int flags);
^
rbzmq.c: 関数 ‘socket_recv’ 内:
rbzmq.c:1596:9: 警告: ‘rb_thread_blocking_region’ は廃止されました (宣言位置 /usr/include/ruby/intern.h:839) [-Wdeprecated-declarations]
rb_thread_blocking_region (zmq_recv_blocking, (void*) &recv_args,
^
rbzmq.c:1602:9: エラー: 関数 ‘zmq_recv’ へ渡す引数が少なすぎます
rc = zmq_recv (s, &msg, flags);
^
In file included from rbzmq.c:28:0:
/usr/include/zmq.h:350:16: 備考: ここで宣言されています
ZMQ_EXPORT int zmq_recv (void *s, void *buf, size_t len, int flags);
^
In file included from /usr/include/ruby.h:33:0,
from rbzmq.c:22:
rbzmq.c: 関数 ‘Init_zmq’ 内:
rbzmq.c:1675:50: エラー: ‘ZMQ_HWM’ が宣言されていません (この関数内での最初の使用)
rb_define_const (zmq_module, “HWM”, INT2NUM (ZMQ_HWM));
^
rbzmq.c:1676:51: エラー: ‘ZMQ_SWAP’ が宣言されていません (この関数内での最初の使用)
rb_define_const (zmq_module, “SWAP”, INT2NUM (ZMQ_SWAP));
^
rbzmq.c:1683:57: エラー: ‘ZMQ_MCAST_LOOP’ が宣言されていません (この関数内での最初の使用)
rb_define_const (zmq_module, “MCAST_LOOP”, INT2NUM (ZMQ_MCAST_LOOP));
^
rbzmq.c:1698:64: エラー: ‘ZMQ_RECOVERY_IVL_MSEC’ が宣言されていません (この関数内での最初の使用)
rb_define_const (zmq_module, “RECOVERY_IVL_MSEC”, INT2NUM (ZMQ_RECOVERY_IVL_MSEC));
^
Makefile:224: recipe for target ‘rbzmq.o’ failed
make: *** [rbzmq.o] Error 1

Gem files will remain installed in /home/aki/.gem/ruby/gems/zmq-2.1.4 for inspection.
Results logged to /home/aki/.gem/ruby/gems/zmq-2.1.4/./gem_make.out

libChat::ZMQにしてもZeroMQを使っているので試せない。サーバー用にVMを用意するなどすればいいのだが、なかなか厄介な事態だ。

簡易的なOP25B対応

様々な仕事が滞っている中なので、先行してメールを送れるようにだけはしておいた。

OP25Bとは、SMTPサーバーポートである25をISPが中継しない、というものだ。スパム対策だというのだが、実際は自由にメールを使わせない、メールをISPで一元化するものとなっている。

メールアカウントが提供するサーバーをそのまま使っていれば特に不自由は感じないという人もいるだろうが、近年のSMTPサーバーサービスはかなり複雑に認証され、フィルタされることもあって使い勝手は著しくよくない。以前ならそれに対する対応としてローカルなメールサーバーを使えばよかったのだが、今度はそれがISPによって蓋をされた格好になる。

各家庭でMTAから出す、ということそのものが特殊な要求と見るのかもしれないが、今はそもそもSMTPサーバーを提供しないメールアカウントも珍しくないので、やはりの必要だし、自宅でのメールサーバー公開もできない。

とりあえずシンプルな方法として、セキュアで確実にリレーしてくれるMTAが欲しい、ということで工夫してみた。

まず、VPSにPostfixを導入する。そして、次のように設定する。

inet_interfaces = localhost
mynetworks_style = host

これ以外についても適切に設定するが、これで外部からメールを受けとらないためセキュアな設定となる。もちろん、外部からメールを受けとるように設定する場合には、より広く適切な設定が求められる。

この状態ではSMTPを用いてメールを送信することができるのはVPS自身だけだ。しかし、VPSのループバックインターフェイス経由ならば送信できるため、SSHのポートフォワーディングを用いることで他のホストからのメールを中継してもらうことができる。

これには次のコマンドを使用する。

$ ssh -x -L 2500:localhost:25 remorthost.example.com

「ローカルの1024以下のポートを転送する場合、ローカルのroot権限が必要」なのであり、ここでは2500番ポートをリモートの25番ポートに転送することでroot権限なしに実現している。なお、リモートホストの名前はlocalhostにしないと、loインターフェイス経由での接続にならないので注意が必要。インターフェイスを気にしなければFQDNで指定しても接続できてしまうことがあるから、理解していないことがある。

-Lオプションのまんなかのargは、後で指定するhostが名前解決をし、接続するための名前だ。つまり、localhostを解決するのは、リモートホストで、リモートホストにとっての::1/127.0.0.1に接続される。

-nオプションを使えばバックグラウンド接続が可能なはずだが、ServerMans@VPSではそれができなかった。接続そのものが切られてしまう。タイムアウトして接続は切られてしまうし、不要なターミナルセッションが生まれてしまうが、通常通りのログインとした。

あとはMUAのSMTPサーバーとしてlocalhost:2500を指定すれば、MUAはVPSのPostfixとやりとりをしてメールを送信することになる。通信はssh(通常は22番ポート)を経由するため、25番ポートをブロックするOP25Bにはひっかからない。

VPSの活用方法としては一般ユーザーでも意味のある方法になるのではなかろうか。もっとも、セキュリティ管理などを考えれば一般ユーザーに進められる方法ではないが。