Gtkなデスクトップ環境でGtkとQtのテーマと格闘する

Gtk環境でのQt

作業環境はManjaro XFceであり、実際の利用環境はCinnamonで、KDE Plasmaは入れていない。

KDE環境だとQtのstyle (QtだとthemeではなくてVisual Styleと呼ぶ。Windows風)は色々入っていたりするのだけども、こういうGtkデスクトップ環境だと古臭いの(ClearlooksとかMotif)とかしか入っていなかったりして、Qtアプリの見かけがだいぶよろしくない。

そこでまず、QtらしいStyleを導入する。 Qt4とQt5のStyleは分かれていて、Manjaro/Archだとkde4やkde5という名前で分けられているようだ。 とりあえず見た限りplasmaパッケージに含まれてはいるものの、KDE本体に依存するようなパッケージはない模様。

Qtのテーマ設定はQt4はqtconfig-qt4、Qt5はqt5ctで行う。

これでKDEとは関係ないけれどQtを使うアプリ(例えばEksterteraとかq4wineとか)の見た目がよくなり、 Ruby qtbindingsも快適に使うことができる。

そう、そもそも今回、ruby-qtbindingsを使ったら見た目がひどかったことからスタートしているのだ。

Gtk2テーマ

Gtk2は恐ろしく鬼門だ。 特に厄介なのが次のアプリ

  • Sylpheed / Claws Mail
  • Mikutter
  • Leafpad

なぜならば

  • Sylpheed / Calws Mailはテーマによっては起動しない。
  • Sylpheed / Claws Mail / Mikutterはスクロールバーがおかしいテーマが多い
  • MikutterはBreezeテーマなどタブの表示が変になるものも多い
  • スクロールバーずれ程度で問題がなく美しいOxygen-GtkはLeafpadはSEGVる

Leafpadを分離するのが良案か。

#!/bin/bash

GTK2_RC_FILES=/usr/share/themes/Adapta-Eta/gtk-2.0/gtkrc exec /usr/bin/leafpad

なお、Gtk3版のl3afpadを使うという手もある。

XFce4は.gtkrc-2.0や環境変数で使用するgtkrcを指定していると、全体的にそれに従う。 外観の設定に左右される範囲よりも大きいようだ。

Oxygen-gtkは良いのだけどなかなか問題がある

  • Gtk3アプリでは表示がおかしくなる可能性が高い
  • Xfce4ではアイコンが反映されなくなる
  • 部分的にUIフォントを頑なに無視する
  • もう開発も止まっているようで今後使えなくなるかも

安定して使えるGtk2テーマがなくなるのはなかなか痛い。見た目はよくはないが、XFceテーマシリーズが安定しているようだ。

Gtk3

Gtk3のほうはもっとシンプル。

Gtk2テーマを指定してXFceを起動すると、Gtk3テーマもそれに従おうとするので、明示する必要がある。

Gtk3も同一テーマで構わないものであれば良いのだが、oxygen-gtkは駄目だ。

if [[ $DESKTOP_SESSION == xfce ]]
then
  export GTK_THEME=Adapta-Eta
fi

しかし、これでもアプリケーションから開くときにGeditを指定するとOxygen-Gtkを使用してしまう。 同様のケースでGeditはfcitxが死んでいる状態で起動したりするので、コマンド名で指定して起動する必要がある。

Cinnamonではデスクトップ設定が反映されるので設定しないほうが良い。

GUIツールキットのお話

今回はRuby qtbindingsを使おうとしたところからスタートした。

RubyでのGUIはまるでスタート廃れたかのような状態にあり、まるでruby-gnome2が唯一の選択肢であるかのようである。 ただ、ruby-qtbindingsは開発は継続しているし、Windowsでも動作するようになっているようだ。

個人的にあまりGtkは好まない。 UIとして使いにくいというのもあるし、設定が複雑でうまく反映されないというような理由もある。 プログラミング上も、QtのほうがAPIは使いやすい。

UIとして優れているのはGtk2だと思う。

Gtk3はメニューが非常に少なく、わかりにくい。 また、ファイルダイアログが劣悪で、ファイルを開くときはまだ良いのだが、ディレクトリを開く場合は非常に辛い。 というのは、何もファイルを選択しない状態で入力を開始した場合のみキーボードからのパス入力を受け付けるが、 Enterを押した時点で「開く」動作をする。 そのため、ディレクトリを開く動作のときには最後まで入力するか、クリックするかしか選べない。

Qt4/Qt5のダイアログはファイル名としてディレクトリパスを入力することもできるが、やはりディレクトリを開く場合には一発で開かれてしまう。 さらに登録される場所がさらに限定的となり、Gtk3よりなお悪い。 なお、XFce4ではQtのファイルダイアログをGtk3のものに置き換えるようだ。

Gtk2のファイルダイアログではファイルリスト側にフォーカスされていればWindows同様にインクリメンタルサーチとなり、 ファイル名欄が常に存在しディレクトリに対して入力を行うとまずディレクトリに移動するという振る舞いとなっている。 これはおそらく最も適切である。 (だが、これも場合によるようで、Qt4/5のような振る舞いをする場合もある)

API的に、あるいは設計的に見ればGtk2からGtk3、Qt3からQt4というのは大幅に進化している。 実際に「よくなった」のだ。

だが、現状でGtk3、あるいはQt5の熟成度というのは全く足りていない。 Qt4からQt5はある程度の互換性を持った状態で進化している。 その進化はわからないでもない。コンピュータの進化に合わせて、あるいは周辺環境の進化に合わせてコンポーネントを作り直した。 その際にいくつかのいまひとつな設計を修正し、テーマデザインにフラットデザインを推奨した。

だが、そのような変更は必要だったのか疑問だ。 内部的な進化や、標準テーマデザインの変更に関しては互換性を維持しての改修でもよかったのではなかろうか。

期間的にGtk3やQt5は日が浅い。 Gtk3のコンセプトが不評ということもあるが、2011年にGtk2は開発終了しているにも関わらずGtk3への移行が進んでいないプロジェクトは多い(XFce4もそのひとつだろう)。 現状ではGtk2を採用するプロジェクトもGtk3への移行を模索する時期にきているが、Gtk3に移行できているプロジェクトはまだ少ない。 Qtに関しては各プロジェクトが苦労してQt3から移行を完了し、あるいは移行できなかったプロジェクトは廃止されているが、 Qt4を採用しつづけるプロジェクトはまだ少なくない。

この状態でさらに非互換性を持つGtk4やQt6へ移行する必要があるのだろうか。 いずれのツールキットもより熟成すべきであるように私には思える。

また、GUIプログラミングも以前は盛んでwxwidgetなどが流行したときもあったのだが、早々に廃れてしまった。 WXWidget自体は現在も開発が続けられているが、wxrubyは既に終了しており、rwxは十分に開発・テストされていないようだ。 RubyにおけるGUIプログラミングの選択肢は非常に乏しく、qtbindingsも将来的には不透明だ。

さらに、Gtkのその問題点から開発者が離れている。 これはGtkの問題点というよりも、Gnomeの方針に開発者がついてきていないという問題なのだが、 GnomeはGtk4においても方針を維持しており、今後もこの傾向は続くだろう。

ユーザー側にはあまり見えない状況ではあるが、実はLinuxのGUI周りはかなり不安定な状況にある。 個人的にはQtがより普及し、バインディングが安定していてくれると良いのだが…

Linux的ビデオのハードウェアエンコーディング

ネットで検索するとかなりいい加減な情報が溢れているので、 そこまで分かっているわけではないけれどまとめてみた。

「エンコード」

まずencodeとdecodeがわからない記事がいくつか出てくるのでそこから。

  • データを映像/音声にするのがデコード
  • 映像/音声をデータにするのがエンコード

エンコードは動画編集をしているのでなければ、基本的に動画変換のお話。

ハードウェア

ハードウェアでやる、というのはCPUに頼らず、ハードウェア側に搭載された専用のチップを使用してエンコーディングする話をしている。

これにより

  • CPUにかかる負荷が低減できる
  • 速度が向上する(かもしれない)

というメリットがある。

遅いGPUと速いCPUの組み合わせだと速度向上には必ずしもつながらないが。 だが、GPUは非常に速いので高速化する可能性は高い。

最近の盛り上がり

動画処理というか、変換というかではなくて、 「ゲームしながらゲームを録画するため」 だと思う。

ゲームはリソースをいっぱい近く使うので、録画するのは難しい。 処理落ちなどの原因になる。 そんなことがあったら多分ガチなゲーマーは許さない。

録画時はそのまま映像データを収録しているとあまりに巨大ファイルになる。 ゲームのプレイ時間は長い可能性が高いし、これはこれできつい。 というわけで、これをハードウェアにオフロードしてCPUや描画用グラフィックスに負担をかけることなく録画/変換して保存しようということだと思う。

ただ、IntelのQSVは恐らく趣旨が違う。 というのは、こちらは「CPUやメモリにも負担をかける」からだ。 VP9エンコードにもKaby Lakeにも対応していたりするので、もしかしたら動画編集を意識しているのかもしれない。

VA-APIとVDPAU

VA-APIはIntelが、VDPAUはNvidiaが作ったLinux用のハードウェアビデオアクセラレーション用のAPIだ。

それぞれサポートされているのだが、そのサポートに注意がいる。

  • libva-vdpau-driverはVA-APIをラップしてVDPAUに投げる
  • libvdpau-va-glはVDPAUをラップしてVA-APIに投げる

このため

  • NVIDIAはVA-APIは使えるけれど実際はVDPAUを使用する
  • IntelはVDPAUは使えるけれど実際はVA-APIを使用する

ちなみに、AMDのオープンソースドライバ(ATIあるいはamdgpu)はVA-APIドライバとしてlibva-mesa-driver(とmesa)と、libva-vdpau-driverの2種類の方法がある。 前者であればVA-APIを直接取り扱う。後者であればVDPAUに流す。

そして、重要な点

  • VDPAUはハードウェアデコード用
  • VA-APIはハードウェアエンコード/デコード用

つまり

  • NvidiaのカードはVA-APIをサポートしていないのでこの方法でのエンコードは無理
  • AMDのカードはlibva-mesa-driverを使わないとハードウェアエンコードできない

ハードウェア側機能

IntelにはQSV, NvidiaにはNVEnc, AMDにはVCEがある。

QSV (Quick Sync Video)

デコードだけじゃなかったんだぁ…と思ってしまったけれど、 実はIntelのビデオアクセラレーションは割とLinuxに手厚い。

QSVの利用はIntel Media Server Studioを要求されるけれども、色々と条件が厳しいし、フリーではない(無料ではあるけれど)。

性能的には劣るもののVA-APIから叩けるらしい。

VCE (Video Coding Engine)

デコード用のUVD(Unified Video Decoder)とセットのAMDの機能。

VA-API経由で叩ける。

NVEnc

Nvidiaのエンコード用ビデオアクセラレーション。 Pascal世代になってとっても速くなったらしい。

Maxwell Gen2でもHEVC 720p高画質で300fpsとか言っているのでGPUすごい。

QSVのほうが速いとか言っている人がいるけれども、多分そんな環境まずない。

画質が割と腐っているけれど、H265がH264とほぼ同じ速度で変換できるので、H265にすればだいぶよろしくなる。 H265エンコードはMaxwellからのサポート。

エンコーダと画質のお話

ハードウェアエンコードを行う場合、実際のデータ変換処理を行う「エンコーダ」としてハードウェアへのアダプタを指定する。

つまり、NVEncを使う場合、libx264の代わりにnvenc_h264を使うことになる。 なのでエンコーダオプション(-crfとか)も変わる。

結果的に変換のされ方が変わる。 同一のクオリティを要求しても同じデータにはならない。

そして、ハードウェアエンコードを行った場合の画質、あまりよくない。 H.264でq=30くらいまで落とすとものすごくわかりやすいことになる。 q=28でも厳しい。

画質が悪いのだからできれば「保存したい」よりも「消すのはちょっと…」くらいのモチベーションの動画で使いたいところなのだが、 そういう動画こそサイズを小さくしたい。 ところが、ハードウェアエンコーダでサイズを小さくすると画質が目立って悪い。 だいぶ悩ましい話だ。

ffmpegでエンコード

Linuxの動画はffmpegで変換するものでしょう?

というわけで、QSVとVCEはVA-APIに対応しているのでVA-APIで。

ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 -vf 'format=nv12,hwupload' -c:v h264_vaapi output.mp4

エンコードもハードウェアでやればより軽い。

ffmpeg -init_hw_device vaapi=foo:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device foo -i input.mp4 -filter_hw_device foo -vf 'format=nv12|vaapi,hwupload' -c:v h264_vaapi output.mp4

-qオプションは指定できるみたい。

ffmpeg -init_hw_device vaapi=foo:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device foo -i input.mp4 -filter_hw_device foo -vf 'format=nv12|vaapi,hwupload' -c:v h264_vaapi -q 28 output.mp4

Nvidiaがひとり独自路線なのはちょっと気になるけれども、使いやすいのはnvencのほう。

ffmpeg -i input.mp4 -c:v nvenc_h264 -q 28 output.mp4

qの値など実際は探り探りやっていくしかない感じ。

あなたのビデオカード、眠ってませんか

GPUは基本的に積極的に働かせないと動かない子なので、 結構なリソースを眠らせている可能性は結構ある。

Linux環境だとCinnamonとKDE Plasmaがハードウェアアクセラレーションに対応しているため、 割と最近のIntel CPUやAMD APUを搭載しているコンピュータだとCPU的にはXFceやMATE、LXDEなんかよりよっぽど軽かったりもする。

そういうのがあればある程度は働いてくれるのだが、これもビデオカードの機能のごく一部を使っているだけ。 ちなみに、OpenGL用のアクセラレータを使っている。

この状態でもデコーダやエンコーダは遊んでいるので、せっかくのリソース活用してあげてください。

ハードウェアエンコーダの画質はちょっと微妙だけども。

ブログわけました + DeleGateのバグ

tech系のアクセスと、非tech系の記事のアクセスが交錯して、あまりよくないことになっていたので、分割することにした。

これに伴って両方ともアドレスを変更、現状、journal.reasonset.netはChienomiのほうに転送されるが、将来的にはJournal de Akiのほうに転送される予定。

Journal de AkiはおおよそデイリーPVが4000ほどで、3000がtech、1000が非techになる。 分割してからは700ほどまで低下している。 固定ページに飛ばしていたのだが、ここでアクセスが切れるケースが多かったので、5日の夕方にmovedを返すように変更した。

今回の変更では従来よりもプロキシの数がひとつ減っている。 というのは、DeleGateのバグにかかってしまったためだ。

MOUNT="/journal/* .../*"
MOUNT="/* .../* nvhost=journal.reasonset.net"
MOUNT="/* .../* nvhost=blog.reasonset.net"

という記述をしたところ、新しい転送先にjournalというアドレスが含まれていたためか、どうしても転送先に/journal/*相当の転送をしてしまうのだ。

そんなこともあったのだけれど、まぁ、Mimirを含めてブログは充実させていく予定なのでほどほどに期待しておいてほしい。 最近いそがしくてあまり書けていないけれど。

Linuxデスクトップが使えないというのなら、知識を授けるのは私の使命だから

齋藤貴義さんのブログが誤謬満載だったので、突っ込んでみる。

e-Taxが使えない

そんなことはない。 実際私e-Tax使っているし。

Blu-Rayの再生が難しい

日本における法的な意味ではやや難しいが、実用的な意味ではそれほど難しくない。 日本の法的にも再生自体を禁じるものはない。 普通にlibblurayで再生もできる。

すごく単純に言えば、lubbluerayを用意しておけばmplayerで再生できる。

地上波デジタルの視聴が難しい

まぁ、それはそうなんだけれども、パソコン上でテレビを見なければならない必然性と、そもそもテレビの必要性からいってそんなに重大なことなんだろうか。 ましてLinuxerにとって。

ハイバネート設定が難しい

難しいのはディスクを暗号化した場合と、swapを切らなかった場合だ。 そうでなければインストーラがよきにはからってくれる可能性は高い。

ただし、うまく復帰できないケースはあまり少なくない。 このようなケースにおいて設定によって改善できる場合もその設定を行うのはかなり難しい。

省電力設定が難しい

メーカー製PCの場合、プリセットが充実していたりするので、多分それのことをいっているのだろう。 そんなものはないが、別に対して難しくもない。せいぜい細かに設定できる程度の話だ。

最も細かく設定できるのは恐らくKDE Plasmaだが、それでも項目自体はThinkVantageによるものと大差ない。 プロファイル切り替えに関してはアクティビティを使うのが楽。

輝度設定キーが動かない

輝度設定用のキーはXF86XK_MonBrightnessUp及びXF86XK_MonBrightnessDownとして定義されている。 XFキーが動かないというのはどういう状況なのかわからない。モダンなデスクトップを使え。

タッチパネルをオフにできない

タッチパネルをオフにする必要があるのか?タッチパッドのことか?

タッチパッドの制御に関しては、Linux版のSynapticsドライバーのほうがWindows版のものよりも細かに制御できる。 タッチパッドをオフにするためのオプションはSynapticsのみならばlibinputにすら存在する。 まだ現時点ではlibinputという選択肢はハードなので、Synapticsは単純に無効にするには

synclient TouchpadOff=1

でいい。

プリンタやスキャナの設定が難しい

最近はFoomaticも充実してきたし、特に困ることはなくなった。 以前はプロプライエタリドライバでないと動作しなかったMP630も最近はFoomaticに含まれている。 現在はPhotosmart-6620seriesでFoomatic+hplipできちんと動作している。

細かな制御、が何を意味しているかわからないが、縁無し印刷や両面印刷もできているし、ミリ単位の修正も一応できる。 インク残量もちゃんと見える。

ただし、ドキュメントスキャナに関しては、紙のサイズの自動判別ができないため、Windowsでやったほうがいい。

スマホとの同期が難しい

同期というのが何をさしているのかわからないが、特になにかができないと感じたことはない。 というか、adbを簡単に叩けるのだから簡単ではないか。それともiPhoneなのか。

デスクトップ環境のUIがイマイチなのが多い

好みの問題だと思うけれど、じゃあWindows 10のあの腐ったUIが良いのか?

私はCinnamonを使っているが、非常に快適である。何の問題もない。 KDE Plasmaは流儀が少々Windowsとは異なるが、十分なパワーがあり、使いこなすことができれば極めて快適だ。

NTFSやHFS+の書き込みに設定が要る

何を言っているのかわからない。

NTFSに関しては、普通はntfs-3gで読み書きするだろうし、設定なんか全く必要ない。 それどころか、NTFSに対する操作のためにLive Linuxを使うことすらある。

ただし、設定はいらないにしても、NTFSの操作にはやや問題はある。ファイルシステムのエラーを発生することが多いのだ。

HFS+が使えないということも聞いたことがない。

サウンドやカメラの詳細設定が難しい

最近はほとんどのサウンドカードやWebカメラが動くけど

それは嘘だ。動かないものは動かない状況は変わっていない。

だが、動くものに関しては設定というのが何をさしているのかわからないが、別に難しくもなんともない。 PulseAudioであればWindowsではとても考えられないような複雑な操作も可能だ。

もちろん、DTM用のオーディオインターフェイスのような設定は難しいが、常識的な範囲での(Windowsの一般的なユーティリティレベルでの)設定はより細かに、容易にできる。 イコライザなんかの話をしたいのかもしれないが、PulseAudio Equalizerというものがあるよ、と教えてあげよう。

Bluetoothデバイスの一部でペアリング出来ないものがある

これは経験がない。Bluetoothアダプタ自体が動作しなかったことならある。

ブラウザで閲覧できないサイトがある

UserAgentをホワイトリストで許可しているサイトの場合、推奨ブラウザでアクセスしても閲覧できない場合がある。UserAgentを書き換えてアクセスし直す必要がある。

これはLinuxの問題ではなく、サービス提供者の性悪さによる問題だし、それくらい対応しろよと思う。

IMEで良いものが少ない

Atokの大分昔のものは動くけど、基本はMozcなどで頑張るしか無い。拡張辞書必須。

現在のAtokが他と比べて快適なのか、ということ自体に疑問があるけれども、Mozcに何の不満があるのだろう。

Mozc Neologd UTまたはMozc UT2の場合、辞書の収録数はGoogle日本語入力よりも上であったはずだ。 なんならウェブ変換エンジンを利用することも可能なので、別に変換精度自体は劣るということはない。 まぁ、実際のところ語彙の問題ではなく、Google日本語入力には劣る面もあるのだが、取り立てていうほどのことはない。

最近はMS-IMEが大変に快適な変換をしてくれるように大変身したので、その意味では辛いものがあるかもしれないが。

なお、そもそもMozcはIMEではなくて、かな漢字変換ソフトウェアである。 IMEというのは、FcitxやiBusなんかのことだ。

KindleアプリのLinux版が無い

そんなことを言ったらMac版もない。

それでWINEで動かすことにどれほどの支障があるのかというのは疑問。 WINEが嫌いか?敗北感でも感じるのか?

Evernote公式アプリのLinux版が無い

公式に説明がある

つまり、公式アプリでないことをEvernote側で受け入れており、そもそも公式クライアントであることに意義はない、ということだ。

LINEアプリのLinux版が無い

wineで動かすしかない。

そもそも4.8, 4.9に関してはwineで動作させることができなかった。

Linux上でLINEを動かす方法としては、Chromeアプリ版(先があまりないが)と、libpurpleによる非公式版がある。

いずれも通話できないといった意味で完全ではないが、最低限動作はするはずだ。

画像編集ソフトが限られる

GIMPで大体のことはできるけど、PhotoshopやSketchのようなソフトは使えない

Windows向けの特定ソフトウェアが使えないことを嘆くのは不毛極まりない。

RAW現像手段も限られる。

yaourtでrawと検索すると309件、「raw image」でも43件ヒットした。

SteamがUbuntu版しか提供されていない

Manjaro Linuxではデフォルトインストールであり、PCLinuxOS及びMageiaでも導入可能。

SlackアプリがFedoraかUbuntu版しか提供されていない

AURにある。

Gitクライアントで良いものが無い

Windows版Gitクライアントは基本的にgit guiと同等のものではないか。 これが快適だとはどんなにがんばっても思えないが。

他にもまぁまぁあるが、Zshより快適なGit環境はそもそもないと思う。

入力デバイスの操作がイマイチ

全く意味がわからない。 入力デバイスの操作はハードウェア的なものでLinux関係ないと思うが。

マウス系のホイール操作はエミュレート精度が

解釈可能な日本語でお願いしたい。

ちなみに、Qt環境では驚くほど滑らかなスクロールが可能で、 さらにタッチパッドの場合はLinux版Synapticsのサーキュラースクローリングの快適さはWindowsになくて苦痛になるものの代表格だと思っている。

それともボタン3クリックの話をしているのだろうか? それであるならばArch wikiに多くの情報がある。

Discord Webhook + curlでスマホに通知してみる(LINE Notifyもあるよ)

IFTTTに近いかもしれないが、特定の条件で発生するアクションを作ったのだが、Linuxコンピュータで処理しただけでは外出中に気づくことができない。 そこでスマホに通知する方法が欲しくて考えた結果、もっとも適切そうなのは、DiscordのWebhookを使うというものだった。

通知までの考え方

一般には次のような流れになる

  1. 検証すべきデータを取得する
  2. データを解析する
  3. 条件を満たす場合にhookを実行する

データ取得、解析は、例えばウェブスクレイピング。次の例では特定のページが最終取得時と変更されているかをチェックする

getfunc() {
  curl 'http://journal.reasonset.net/' > ~/tmp/new.page.html
}

checkfunc() {
  if cmp ~/tmp/new.page.html ~/tmp/old.page.html
  then
    return 0
  else
    rm ~/tmp/old.page.html
    mv ~/tmp/new.page.html ~/tmp/old.page.html
    return 1
  fi
}

ここでhookさせるべきときに1を返すのは、whileで処理しやすいようにするためである。

データの解析までは通常ひとつづりで行われるため、まとめてしまって構わない。 Ruby + Nokogiri + Capybara + Poltergeistという構成でスクレイピングする場合もあるだろう。

また、twによってツイッターの投稿をチェックしたり、IMAPメールボックスをチェックしたり、あるいはfetchmailで受信したメールをフィルタするという方法もあるでしょう。

hookについては、次のようなものが考えられます。 まず、通知を表示する。

notify_hook() {
  notify-send "$1"
}

音を鳴らす。SOXを使うか、mpvを使うか、aplayを使うか…など選択肢は多いのですが、ここではSOXを使うことにしましょう。 音が鳴り終わるまで止める必要はないので、バックグラウンドで

notify_hook() {
  play "$1" &
}

ダイアログを表示する。Zenityの場合、制御端末が存在していると、制御端末ウィンドウがアクティブにならないとダイアログが表示されないため、ここではYadを使います。

notify_hook() {
  yad "$1"
}

コマンドを実行する。hookが起動された時点で実行したい内容があれば書いておきます。

notify_hook() {
  tw --yes "HOOKされたよ!"
}

スマートフォンに対する通知

Linuxコンピュータの前にいればユーティリティを自在に書くことのできる我々は全能感にすら浸ることができる。 だが、残念ながらLinuxコンピュータで優れたスクリプトを書いていたとしても、それはLinuxコンピュータに触れていなければ十分に発揮することができない。

そんな外の世界をつなぐのがスマートフォンの存在だ。 スマートフォンが注意をひきつけてくれれば何かしらの対応が可能だろう。

最も簡単な方法はメールではないだろうか。昔からよく使われていた方法だ。 現在もその方法は有効であり、例えばMailxを使ってメールを送ることもできる。 次の例ではMailxは設定済みであるか、もしくはlocalhsotに有効なMTAがあるものとする。

notify_hook() {
  echo "Hookされました" | mail -r "notification@localhost.localdomain" -s "Hooked notification" mms@example.com
}

だが、今時MMSなんか使っていないというHackerも多いのではないだろうか。 GMail宛に送るという方法もあるが、GMailで大量のメールをもらっているからあまり参考にはならないという人も多いはず。

ではインスタントメッセンジャーについて検討してみよう。

Facebook Messangerはfb-messanger-cliやMesserなどがあるが、自分自身に送るためのハードルが高すぎるため現実的ではないだろう。

Google Hangoutsはhangupsによってコマンドラインからの送信が可能だ。 ただし、Pythonスクリプトで書く必要があり、それなりに複雑だ。事前準備もある程度必要で、bot用アカウントを作成しておかなければ自分自身には送れないという意味でハードルは高い。

SkypeもSkype4pyによってコマンドラインから利用が可能だが、問題はHangouts同様である。 最近はSkypeアカウントの認証は厳しいし、サードパーティクライアントに対して非常に厳しい対応をとっていることを考えるとより難しいだろう。

以外にもLINEは現実的な処理が可能だ。 LINE Notifyのマイページから登録を行い、トークンを取得する。 そして次のようにして送信するのだ([token]と[message]は適切に置き換える)

curl -X POST -H 'Authorization: Bearer [token]' -F 'message=[message]' https://notify-api.line.me/api/notify

有力な選択肢のひとつである。

SlackはBOTを作成することができ、簡単に通知することができるが、Slackの通知は安定しないため、すぐに気づきたい場合に見逃すかもしれない。

Discordを使う

LINEで通知できるのも素晴らしいが、Discordならもっと楽しい。

Discordはマルチプラットフォームであり、PC, Android, iOSで扱うことができる。 加えて、それぞれの端末にアカウントを分けることで電話番号のない端末を探したり、一斉に通知したりすることが可能だ。

しかも、LINEでは通知はすべてがまとめられてしまうが、これなら分類することもできる。 LINEにおいても自分のみが所属するグループを作ることで共有が可能だが、Discordのほうが共有も容易だ。 URIなどを端末間で共有したい場合の利便性も高い。

まずは準備をしよう。 各端末にアカウントを用意し(PCと共有のアカウントがあっても構わない)、自分(たち)用のサーバーを用意する。 そして各端末のアカウントを招待し、通知/共有に含めたい全アカウントを登録する。

これでgeneralを介してアクセス可能になったが、全てがまとめられてしまう状況には変わりない。 そこで、内容を適切に分割するようにチャンネルを作成しよう。

チャンネルをわけることで、そのチャンネルに対する内容を通知しなくていい端末は当該チャンネルの通知を切っておく、ということも可能になるる これにより内容によって端末に通知する/しないを選択可能だ。

ではいよいよWebhookを作成する。 チャンネルの設定に移動し、"Webhooks"を選択する。ここでWebhookを作成するとWebhookの名前とアバターを設定し、通知するチャンネルを選択、そしてURLが発行されるはずだ。 このwebhook URLに対してJSONをPOSTすることでbotとして発言させることができる。

Webhookに対して送れるJSONオブジェクトは次の通りだ。

Field Type Description Required
content string 2000文字までのメッセージ 1つのcontent/file/embeds
username string Webhookのusernameを上書きする false
avatar_url string デフォルトのアバターを上書きするURL false
tts bool trueならTTSメッセージとする false
file file contents 送信するファイル one of content, file, embeds
embeds array of embed objects 埋め込まれたリッチコンテンツ one of content, file, embeds

チャンネルは設定を上書きできないが、発言者の名前やアバターは上書きすることができる。 そのため、単一のWebhookでも種類の異なる通知をすることが可能だ。 (アバター変更するなら複数のWebhookを使ったほうが効率は良いだろうが)

curlを使って次のようにJSONを送信することができる。

curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"username":"J.R.H","content":"ホックされたよ!!!"}' 'https://discordapp.com/api/webhooks/koko-ni-hook-no-uri'

JSONがダブルクォートを必要とするため、変数展開したい場合は少し大変かもしれない。

ひとこと

LINEもDiscordも、ユーザーごと/チャンネルごと個別の通知音設定がほしい

Android Oneで連絡先が本体に保存できない

Y!Mobileから案内がきてPHSを終了し、ケータイへと移行するように求められた。 ちょうどPHSのキャンペーンが切れて費用が上昇したこともあって検討、結果残っていた2回線(元々の3G回線は転出済み)を両方ともケータイへと移行した。

この際、AQUOSケータイ2とAndroid One S2へと移行したのだが、Android One S2において連絡先の保存先に選択肢がなく、本体に保存、あるいはSIMカードに保存することができず、強制的にGoogleアカウントへの保存となってしまう。

これついて調べたが結論を得ることができず、Y!Mobile店舗で問い合わせたところ、Android OneあるいはNexusにおける仕様であるとのことだった。

恐らくこのほかにもGoogleと不可分になっている点は多いだろう。 出ていない情報だが、現状Y!MobileにはAndroid Oneしかないため、Y!Mobileを選択するかどうかの問題になってもくるだろう(Softbank中古端末や、SIMフリー端末を使用するという選択肢もあるが)。 気をつけてほしい。

Discordを使ってみた

Discordというアプリを知っているだろうか。 まぁ、だいたいの人は知らないだろう。

簡単に言えばSkypeのようなメッセンジャー+通話アプリであり、Discordは大声で「Skypeを投げ捨てろ!!」と言っている。 だが、単純にSkypeのようなアプリというわけではない。 ものすごく乱暴に言えばSkypeのような機能と、Slackに通話機能をつけたものを一体化させたものである。

通話とメッセージングのソフトウェア(例えばSkypeやLINE)と比べると結構複雑だ。 これは「2つの側面がある」と考えてもらうと良いだろう。

Slack的な部分

だが、まずSlackを知らない人が圧倒的に多いだろうからそこから説明しよう。

Slackは簡単にいえば共同作業用のチャットツールである。 「Slackのアカウント」というのは基本的に存在せず、「チーム」というのがその単位となる。 「チーム」はメンバーを招待することができ、招待された人はそのリンクを使ってメールアドレスを登録するとそのチームのメンバーとなることができる。 チームでの活動は、チームのアドレス、またはチーム名とメールアドレスを使って行う。

メンバーにはプロフィールがあるが、プロフィールもチームごとに設定する必要がある。 逆にいえば、チームの性質によって異なるプロフィールを使うことができる。 メンバーにはロール(役割)を与えることができ、メンバーを追放する、チャンネルを作成するなどの権限を分けることができる。

チームにはチャンネルがある。 全体の発言は#generalというチャンネルで行うが、チャンネルを作成すれば、話題を分けたり、閲覧できるメンバーや発言できるメンバーを制限することができる。 基本的には議題ごと、あるいはチーム内のメンバー区分ごとにチャンネルでやりとりをすることになる。 メンション機能もあるが、これは特定の人だけにメッセージが届くわけではなく、特定の人に通知を飛ばすだけである。 ユーザーグループというのもあるが、これはメンションを飛ばす時に複数人をまとめて書いたり、チャンネルに加えるときにまとめて書くための機能。

Slackは主にIT企業の業務で使われていて、ビジネスツールというニュアンスが強い。 社内でのやりとりとしてはメールなんかよりよっぽどいいのは確かだと思う。

ただ、逆に言えばそれ以外では全然使われていない。もともとゲーム用のツールだったなんてことは、ほぼ忘れ去られている(私も知らなかった)。

しかし、実のところ、マメ派のカップルにはかなり良いと思うのだ。 デートの予定やイベントの計画、今日の買い物といった話題をLINEでやりとりしていると、どんな話をしていたか確認するのが大変になってくる。 LINEはログをさかのぼりにくいし、ノートに立てていればいいのだが、LINE for Chromeはノート機能がなかったりするし、明確に議題を定めてから話がはじまるとは限らない。 そもそもノートも増えてくると議論には向いていないことになる。 なので、Slackで#date, #event, #todoなどチャンネルを作っておけばスムーズにやりとりや確認ができてとても便利だ。

ところが、LINEを投げ捨ててSlackにいけない理由がある。 まず、割とSlackの通知はまちまちで、あまりリアルタイムではこない。マメ派カップルにとっては割と致命的だ。 しかも通話機能もない。ラブラブなカップルにとってはますますもって致命的だ。

ここでDiscordである。

DiscordはこのあたりはだいたいSlackと同じだ。 大きな違いとして、Slackで「チーム」と呼んでいるものは「サーバー」という名前に変わっている。 そして、通話機能がある。

通話機能がちょっと独特で、1名でも通話をはじめられる。 チャットのように(特にIRCのように)、「通話チャンネルに入っている人が自動的に通話する」という方式だ。 途中参加もできるし、途中離脱もできる。というか、最後ひとりになっても勝手には切れない。 通話チャンネルも複数作ることができる。

また、雑音を積極的に検出し、しゃべっていない時はマイクを切るようになっている。 プッシュトゥトークにすることもできるので、大勢参加していてもノイズまみれにならないようになっている。 これは便利だ。

また、SkypeやHangoutsのグループトークにない機能として、ユーザーごとに音量設定できる。 声の小さい人を大きく、声の大きい人を小さく。好きな人を大きく、嫌いな人を小さくすることが可能だ。

そして重要な違いとして、Slackと違ってちゃんとすぐに通知がくる。

Skype的な部分

だが、Discordの場合はユーザーアカウントがある。

そのため、複数のデバイスでDiscordを使用した場合、自分が参加しているサーバーはすべて一覧されるし、招待するときはユーザー名とDiscord番号の組み合わせで行う。 フレンド登録もできる。プロフィールや名前もサーバーごとというわけではない。

さらにフレンド登録すると、ダイレクトメッセージとダイレクトコールが可能になる。 これはSkypeやLINEのように、人単位でメッセージを飛ばしたり、通話したりすることができるのだ。

ただし、Skypeにあるビデオ通話や画面の共有は、実装予定の機能となっており現在はない。 これを書いている今日テストがスタートしたようだが。

また通話手順がちょっと複雑だ。Discordがフロントにある場合は普通に通話がかかってくる。 ただし、通話をかけた側は通話画面にはならず、右下にあるVoiceの矢印で開かなければチャット画面での通話になる。 これは通話を受けた場合も同様。

また、通話を切っても残った側の通話は自動的には切れない。これはサーバーの場合と同じである。

なんらかの理由で最初からチャット画面に変遷した場合(通知から飛んだ場合などだ)、まずDM画面にいき、JOINをタップしたあと、Connect to Voiceを選択しないと通話に参加できない。 これはなかなかややこしい。

グループDM機能があり、これは招待もなにもなく、グループDMを作成すると招待された全員が自動的に参加する。 グループDMはフレンドリストに登録される。グループから退出したり、グループに追加で招待することは可能。 退出してもすぐ招待されるようなことが起きるとちょっと面倒。最後のひとりになってもグループ自体は消えない。

スタンプ機能はない。写真埋め込みは可能。

Slackに対するメリットとして、日本語に対応している。 Slackが便利でもインターフェイスは英語に限られていたSlackは敷居が高いという人が多かった。

また、ちゃんとしたクロスプラットフォームアプリがあるということも大きい。Slackの場合はアプリケーションもいまひとつだ。

また、Slackのように有料プランがあって、機能が制限されているというわけでもない。

もっと便利な部分

Discordはゲストログインが可能で、サーバーを作ってアドレスを伝えれば、相手がDiscordのアカウントを作らないまま通話することができる。 しかもDiscordにはWeb版があるので、共通の通話可能なアプリがない、あるいはアカウントを教えたくない場合でも通話することが可能だ。 かなり特殊な要求だとは思うが。

残念な部分

通知のオンオフはできるのだが、通知音は変更できない。

ゲーマー向け

Discordがゲーマー向けということで、ゲーマー以外で使っている人をみかけることがない。

オンラインゲームでは多人数協力プレイができたりするので、通話しながら意思疎通ができたほうがスムーズにプレイできるのだ。 従来はSkypeを使っていたようだが、最近SkypeがどんどんダメになっているのでDiscordに移っている人が多いらしい。

だが、微妙にバグはあるが、SkypeもLINEもXMPPも投げ捨ててDiscordで生きていけるくらいには便利である。 実用上の話であって、かわいいスタンプが好きな人は辛いかもしれないが。

ゲーム中は特に言うことがなければ黙っているだろうし、発言者のみ聞こえるようになっているのはこのためだろう。 割とキーノイズもするわけだし。

バグ

3つのバグを発見した。

通話通知がおかしい

P02E(Android 4.1.2)だと、通知音が通話でもメッセージのものになってしまい、一度鳴るだけで終わってしまう。

アプリを殺すと通知されない

CM Securityでクリーンアップしてしまうと通知は届かない。 これはNotifications wake up device.をオンにしていてもダメだ。

なかなか恐ろしい通話ループ

  1. AがBに書ける
  2. Bが出る前にAが切る
  3. Bが通知エリアから通話に出る
  4. BにAからかかってきたと表示される。「出ない」ことができない
  5. Bが通話に参加するとAに呼び出しがかかる。こちらも「出ない」ことができない
  6. BがAが出る前に切ったら立場を入れ替えて3にループする

みんなDiscordしようぜ

良い点

  • SlackとSkypeの合体とか超魅力
  • 日本サーバーのないWebRTCとは思えないほど音が良い
  • Windows, Mac, Linux, Android, iOSに対応
  • ちゃんと通知される
  • 画像も貼れる
  • グループDMやグループ通話もできる
  • Skypeよりはるかに軽い
  • 話題を分けて整理することができる
  • グループの中で特定の人に呼びかけることができる
  • 運営が透明で技術的にも透明
  • 登録も簡単でゲスト利用も可能、個人情報も要求されない

悪い点

  • 若干複雑
  • ちょっとバグがある
  • 通知音の設定ができない
  • 個人情報もいらないので尻尾切りのような残虐行為が気軽にできてしまう
  • キモいスタンプが使えない

WordPressでリバースプロキシを介すると301ループする/X-Forwarded-Forが反映されない

301ループ

リバースプロキシ(DeleGate)の向こうにあるWordPressが301ループするという問題だ。

これはWordPressのサイトアドレスをDeleGateがアクセスするものにしておけば問題は発生しない。 ただし、リバースプロキシを置く以上、バックエンドのアドレスは隠蔽したいわけで、これは望ましくない。

一見、MOUNTオプションとしてvhostでなくnvhostを使用することで解決できるかに思えたが、実際は解決しない。 問題がHostヘッダにあるのは間違いない。

調べると、requested_urlredirect_urlが異なる場合に301でリダイレクトする、ということがわかる。 DeleGateはどうしてもHostヘッダは自分で生成してしまう(スルーしてくれない)ため、Hostを元に生成されるrequested_urlと、サイトアドレスを元に生成されるredirect_urlが一致しない。

そこで、起動設定に以下を加えた

HTTPCONF="add-qhead:X-Forwarded-Host:%I"

だが、WordPressがX-Forwarded-Hostを拾ってくれないのか、それともjournal.reasonset.net:80とポートを含めるためなのか、これだけでは動作しない。

そこで、wpconfig.phpに以下の記述を加えた

$_SERVER['HTTP_HOST'] = "journal.reasonset.net";

Hostが違う場合は無視することになってしまうが、まぁ良いとしよう。 ちなみに、X-Forwarded-Hostの値を代入しても、やはりポートを含むためなのか、動作しない。

X-Forwarded-For

DeleGateでX-Forwarded-Forを設定する方法は

HTTPCONF="add-qhead:X-Forwarded-For:%a"

であるが、これで正しく動作しない。 X-Forwarded-Forの値をとるとどうしてもDeleGateの値になってしまう。

どうも、ブログを設置しているXDomain側もリバースプロキシをもっていて、そこでX-Forwarded-Forを設定しているようだ。

仕方ないので、別の値も与えておく

HTTPCONF="add-qhead:X-Forwarded-Delegate-For:%a"

wpconfig.phpでこちらを使わせる

$_SERVER['HTTP_X_FORWAREDED_FOR'] = $_SERVER['HTTP_X_FORWARDED_DELEGATE_FOR'];

これで実際のアドレスを拾わせることができるようになった。

誤家庭のLinuxで大規模ストレージを取り扱う

ストレージ規模がどんどん大きくなる当システム。次期再編成のためのメモである。 なお、話を一般化するために特殊な箇所は変更してあり、このまま適用できるわけではない。

前提

メインとなるホスト(Host Master A)と冗長ホスト(Host Master B)から60TBに及ぶ巨大なストレージを取り扱えるようにする。

バックアップとしてサーバー(Host Slave)を用いてデータの冗長化を行う。

基本的には無停止が可能なようにするが、HAのような完全無停止を要求するわけではない。

機材

安価に拡張可能なストレージ群を構築するには、NetGear ReadyNAS RN316が良いようだ。 これにNetGear ReadyNAS EDA500を追加することで10万円以内で筐体を用意することができる。ディスクとあわせると、20台60TBで約40万円が必要だ(2017年6月現在)。

バックアップは実際には現在はサーバーによる内蔵とAoEの組み合わせ、とするが、将来的には同様の方法をとるのが望ましいだろう。

構成

NetGearで用意したディスクを、NetGearの機能でRAID5化し(つまり有効ディスク数は18となる)、これをiSCSIで提供する。

iSCSIディスクはHost Master Anyがイニシエータとなり、これをLUKSデバイスとして暗号化/復号化し、その上にbtrfsを構築して利用する。

2台ひと組と考えることで、-m1 -d1オプションを使って無停止性を確保することができる。 だが、実際は一般の利用ではディスク故障を除いたデータが損失するファイルシステム事故は割と少ないので、-m1 -d0あるいは-m1 -dsingle構成にしたほうが良いと考えられる。 -m1 -d1とした場合、ディスク30台を使用して使える容量は9台分となる。

バックアップも基本的には同様に構築する。異なるグループのiSCSIを用意し、btrfsボリュームを作成する。

構築

接続

iSCSIによる通信でほぼネットワークはあふれることになるため、ネットワークは分離することにする。

上流側は主にはクライアントユースになる、と考えれば、上流側をUSBアダプタとすることでホストの切り替えを容易にすることが考えられる。

Host Master AをHost Masterと考えた場合、Host Master A及びHost Slaveが2つのNICを持っている状態 となる。 このとき、両者が所属するネットワーク(サブネット1)はホストネットワークであり、下流側はストレージのみを接続する、という形態にすることでiSCSIの通信を混在することを避けられる。

Host Master Bを使用する場合はHost Master AからUSB NICを取り外し、Host Master Aに接続されていたUSB NICにHost Master Bにささっている(サブネット1の)ケーブルを接続し、Host Master B内蔵NICにはHost Master Aに接続されていたサブネット2のケーブルを接続すれば良い。

NASの用意

NASのディスクを各NAS上でRAID5で構成する。

2台ひと組にしておけば、btrfsは-d1であってもディスクを使い切ってくれる。 -dsingleにする場合は、NAS内のディスクは容量を揃える必要があるが、NASの合計容量を揃える必要はなくなる。

全ディスクを連結してRAID5を作ってしまうと、ディスク容量の制約が厳しくなるので、この方法のほうが良いだろう。 性能面でも、暗号化とRAIDの組み合わせはかなり重いので、速度を考えればハードウェアRAIDのほうが望ましい。

RAID5を構成したディスク上にLUNを作る。 グループはMasterとSlaveで異なるものにしたほうが良いが、Master NASはサブネット2、Slave NASはサブネット3に置かれるため、実際に混在することはない。

ホストのセットアップ

iSCSIイニシエータとして利用するため、iSCSIイニシエータutilのインストールと、iscsiサービスの起動が必要になる。

利用方法については、archwiki参照のこと。

全てのiSCSIターゲットにログインした上、これをluksFormatする。 ディスクは増えていくことになるので、キーファイルを使ったほうがスクリプトにする際に良いだろう。

# cryptsetup luksFormat /dev/sdb /path/to/keyfile

そしてオープンする

# cryptsetup luksOpen --keyfile-/path/to/keyfile /dev/sdb Crypt1
# cryptsetup luksOpen --keyfile-/path/to/keyfile /dev/sdc Crypt2

btrfsファイルシステムの作成

# mkfs.btrfs -L MasterBtrfs -m1 -dsingle /dev/mapper/Crypt[12]

追加で、サブボリュームの作成や、fstabの編集などを行っておく。

iSCSIターゲットの探索とログイン、ディスクの復号化とマウントの一連の流れはスクリプトにしておいたほうが良いだろう。

利用

まずNASを起動し、次にホストを起動する。そして、スクリプトによってマウントする。 セットアップが終われば非常にシンプルである(ただし、スクリプトにしていないと打つコマンドの量は多い。それはそれでセキュアだが)

スクリプトをsystemdユニットにしておくのは良い考えだが、コケる可能性の高いユニットなので、enableにはしないほうが良いだろう。

NFSとファイル配置

NFS v4を提供する。Manjaro Linuxでの手順である。

まず、btrfsのマウントポイントは/mnt/masterであるとする。 しかし、実際には特定ユーザーのデータが配置されるのであり、~foo/.masterfsがマウントポイントである。

そこで、これを反映できるようにするため、スクリプトの先頭で次のようにしておく

mount --bind /mnt/master /mnt/master
mount --make-rshared /mnt/master
mount --bind /mnt/master ~foo/.masterfs

これにより、ふたつのマウントポイントを意識せずに共有することができるようになる。

さらに、ここではNFSのマウントポイントも別に用意する。

mount --bind /mnt/master /srv/nfs4/masterfs
mount --make-slave /srv/nfs4/masterfs

ここまではスクリプトに含めると良いだろう。

NFSパッケージのインストール。

# pacman -S nfs-utils

/etc/exportsの設定

/srv/nfs4/masterfs 192.168.1.0/24(rw,no_subtree_check,nohide)

v2, v3の無効化(/etc/conf.d/nfs-server.conf)

NFSD_OPTS="-N 2 -N 3"

起動。マウントを手動で行っているため、enableは非推奨。

# systemctl start nfs-server

他ホスト(サブネット1のホスト)からマウントするためには、次のようにする。

# mount -t nfs -o vers=4 masterhost1:/masterfs /mnt/masterfs

-t nfs4とする必要がある場合、サーバー側パスにエクスポートルートを含める必要がある場合があるという。

CIFS

Arch系ディストリビューションにおけるSambaのセットアップ手順はArchwikiが参考になるだろう。

Linuxを中心に使っているユーザーにとっては、常時マウントするわけではないから、ファイルマネージャでのusershareシェアで十分かもしれない。

ただし、AndroidユーザーにとってはCIFSで構築したほうがメディアファイルの再生も容易になる。

DLNA

メディアファイルを広く再生する方法として有効なDLNA。

DLNA対応のプレイヤーがあり、それによって大画面で見られるといった場合には役立つだろう。

主にHost Masterを使い、Host Masterにログインすることが前提であるならばRygelで良いと思う。 そうでない場合は、ReadyMedia(minidlnaパッケージ)を利用することが推奨されているようだ。

Archのminidlnaはminidlnaユーザー, minidlnaグループで動作する。 そのため、ライブラリはこのユーザーでアクセス可能でなくてはいけない。

また、面倒を避けるためには、/etc/minidlna.confinotifynoにしておくのが良いだろう。

あるいはユーザーで実行したい場合は

$ install -Dm644 /etc/minidlna.conf ~/.config/minidlna/minidlna.conf
$ vim ~/.config/minidlna/minidlna.conf
$ minidlnad -f ~/.config/minidlna/minidlna.conf -P ~/.config/minidlna/minidlna.pid

のようにする。

DAAP

iTunesを使用しているユーザーにとっては軽快に動作する音楽ストリーミング方法。 forked-daapdが推奨されているが、AURにしか存在しない。

forked-daapdをインストールし、libraryセクションのdirectoriesを設定、当該ディレクトリをdaapd実行ユーザー(デフォルトでdaapd:daapd)がアクセス可能な状態にして

# systemctl start forked-daapd

で動作する。

LinuxではAmarokあるいはRhythemboxで再生できる。 Androidスマートフォンでは、DAAP Media Playerなどがあるようだ。

2008年頃に流行したDAAPだが、既にだいぶ廃れている印象はある。

ストレージとの分離

ユーザーデータ(dotfileなど)にも容量の大きなものがあるため、ストレージに退避したいと考えるかもしれないが、割とそれはリスキーである。

dotfileの場合、ファイルシステムをまたぐと動作しないもの、シンボリックリンクをこえられないものがあったりする。 また、ログイン時においてはストレージから切り離された状態にある可能性もあり、またストレージがダウンする可能性もあると考えなくてはいけない。

つまり、ストレージが切り離されても動作する状態を保ったほうが良い、ということである。

また、作業中のファイルなどは、ストレージとは別にシステム側にもあったほうが良い。ストレージが切り離された時に作業不能になる度合いを軽減するためである。

さらに、xdgディレクトリはシンボリックリンクが切れているとログイン時に変更されてしまう。 そのため、データが大きい~/Pictures~/Videoなどは、単純なディレクトリとして、その下にシンボリックリンクを配置したほうが良い。

運用の一例としてだが、次のようなストレージ構成だとする

sda      Internal SSD      System
sda1     Internal SSD      System, /
sda2     Internal SSD      System, Swap
sdb      iSCSI 1GbE        Data, Btrfs
sdc      iSCSI 1GbE        Data, Btrfs

次のようなマウント結果となる

/dev/mapper/luks-xxxxxxxxxxxxxxxxx on / type ext4 (rw,relatime,data=ordered)
/home/foo/.storage on type btrfs (rw,noatime,compress=lzo,space_cache,subvolid=258,subvol=/master)

ストレージへ同期されるべきものとして以下のように構成する

WorkSpace
+ Documents
+ Dotfiles

製作中のメディアファイルはDocumentsではなく~/.storage/user/art/以下に配置し、Documentsは文書ファイルのみを配置することで軽量なディレクトリにすることができる。

次のようなスクリプトを作っておく

#!/bin/zsh

WS=$HOME/WorkSpace

update() {
  rsync -avH "$@"
}

sync() {
  rsync -avH --delete "$@"
}

gitup() {
  (
      cd "$1"
        git add .
        git commit -m "Synced at $(date +%y%m%d)"
        git push
    )
}

hgup() {
  (
      cd "$1"
        hg add .
        hg commit -m "Synced at $(date +%y%m%d)"
        hg push
    )
}

gitup $WS/Documents
for i in $WS/Dotfiles/*
do
  hgup $i
done
sync ~/Pictures ~/.storage/XDG/
sync ~/Videos ~/.storage/XDG/
sync ~/Mail ~/.storage/

slave系

これでmaster系は54TB(3TB * 20 disks)ものスペースを一台に集約し、そのファイルを他のホストでアクセスするようにすることができた。 NFS/CIFS/DLNA/DAAPでアクセスできるため、ファイルの取り扱いは非常に良いはずだ。

加えてRAID5によりディスク故障やディスク破壊にも対応する。

だが、これでも壊れる可能性はある。誤消去や誤った更新・上書き、NASの故障、Btrfsの修復不能なクラッシュにどう対応するのだろうか?

ここでRAIDとバックアップは違う、という基本に立ち戻る必要がある。 つまり、このように堅牢なシステムを作っても、あるいはBtrfsクラッシュに備えてRAID5 NASにBtrfs RAID1を組み合わせたとしても、バックアップは別途必要なのである。

基本的にバックアップはメインストレージと同等の設備が必要になる。 もしメインストレージをBtrfs RAID1としているのであれば、バックアップにおける無停止性はそれほど重要ではないため、その場合はメインストレージの半分で済むということになる。

つまりおおよそシンメトリカルな2つのストレージ群とホストが編成されることになる。 ただし、slave系のコントローラホストはサーバーであり、処理性能よりも省電力性や静音性が重要となるだろう。 とはいえ、あまりにも処理性能をおざなりにすると、SSHの処理でもたついて時間がかかることになる。

現状で当環境においてはProLiant MicroServerを使用しているが、どちらかといえばラップトップのほうが適性があるとされている。 標準でコンソールを備え、無停電電源装置を内蔵した状態になるからだ。しかも省電力で静音性も高い。 メインホストからみた速度向上のためにはメモリは多目であったほうがいいだろう。

構築、ストレージへの接続、Btrfsの作成は同様である。

バックアップはBtrfsのsend/receive機能を使うことができる。 差分バックアップも用意で、本当に変更されたものだけを転送するため、非常に効率が良い。

次のようなスクリプトを用意する。

#!/bin/zsh

notify-send "BtrSnapSync: Woke"

if ! btrfs subvolume snapshot -r /mnt/master /mnt/master/snapshots/snapshot-new
then
  print "BtrSnapSync: **CRITICAL** Failed to create new snapshot"
  exit 2
fi

sync

notify-send "BtrSnapSync: Snapshot."

if [[ -e /mnt/master/snapshots/snapshot-old ]]
then
  if btrfs send -v -p /mnt/master/snapshots/snapshot-old /mnt/master/snapshots/snapshot-new/
  then
    notify-send "Send Snapshot."
    btrfs subvolume delete /mnt/master/snapshots/snapshot-old
    mv /mnt/master/snapshots/snapshot-new /mnt/master/snapshots/snapshot-old
    notify-send "Deleted old Snapshot."
  else
    notify-send "Failed to send Snapshot"
    btrfs subvolume delete /mnt/master/snapshots/snapshot-new
  fi
else
  if btrfs send -v /mnt/master/snapshot-new
  then
    notify-send "Send Snapshot."
    mv /mnt/master/snapshots/snapshot-new /mnt/master/snapshots/snapshot-old
    notify-send "Deleted old Snapshot."
  else
    notify-send "Failed to send Snapshot"
    btrfs subvolume delete /mnt/master/snapshots/snapshot-new
  fi
fi

また、slave側は次のようなスクリプトを用意する。

#!/bin/sh
btrfs receive /MirrorRoot && mv /MirrorRoot/snapshot-new /MirrorRooot/snapshot`date +%y%m%d%H%M`

あとは次のようにすることで転送する。

$ btrfssend.zsh | ssh -i /root/.ssh/btrfssnapsync root@slave.local /usr/local/sbin/btrfsreceiver.sh

暗号化を行わず処理を軽減するには、まずslave側で次のように実行する(OpenBSD Netcatを使用している)

# nc -l 12358 | btrfsreceiver.sh

続いてmaster側。ここではbashを使っている。

$ btrfssend.zsh > /dev/tcp/slave.local/12358

暗号化の必要がないとしても、危険だと考えられるため、SSHの利用が推奨される。

LinuxにおけるSkypeとPulseaudioを用いたスプリット/ミキシング

Skypeに関して

2017-07-01よりSkype Linux (4.3)は利用不可能となった。 ということであるが、実際のところまだ使うことができている。とはいえ、将来的には使えなくなる可能性は高い。

後継となるのがSkype for Linux (5系)である。Skype for LinuxはSkype for WebやSkype for Windwos Desktopに近い、最近のSkypeっぽいUIである。

最近はSkype Linuxの動作が安定しなくなっていたが(チャットの取りこぼし、ビデオのフリーズなど)、Skype for Linuxは動作も安定していて信頼できる。

バージョン2までのSkypeがSkype4Linuxと呼ばれていて、バージョン3でSkype Linuxに変わったということを考えれば、Skype for Linuxという名称に変更されることは混乱を招くものだと感じる。 ただし、現在は他のアプリケーションもSkype for xxxの名称に統一されているため、Skype4Linuxはなかったことにしたほうが美しいのか。

ただし、これに伴ってSkype Call Recorderは利用できなくなった。 これについては、Skype for Linuxでは利用できず、また新規APIが公開されていないため対応もできないと説明がなされている。 API公開がされれば対応する気はありそうだ。

PulseAudioで録音する

Skype Call Recorderが利用できなくなったため、Skypeを録音することができない。

ここで活躍するのがやはりPulseAudioである。 PulseAudioは様々なサウンドコンポーネントのフロントエンドとなるだけでなく、音声ルーティングに関する多彩な機能を持っている。

まずは録音するための仮想sinkを作成する。module-null-sinkによって実デバイスとリンクされていないsinkを作ることができる。

$ pacmd load-module module-null-sink sink_name=MySink           # MySinkというNull Sinkを作る。
$ pacmd update-sink-proplist MySink device.description=MySink   # MySinkの情報をupdate。これでMySinkと表示
$ pacmd load-module module-loopback sink=MySink                 # Monitor of null出力を追加する。やらなくても使えるし、null出力のままだから、不要かもしれない

これでSkypeの音声出力をMySinkとし、Monitor of null出力を録音することで録音自体は可能になるが、それでは通話を自分が聴くことができなくなってしまう。 そこで、Skypeの音声をMySinkと実際の音声デバイスの両方に出力する。これはmodule-combine-sinkによって実現できる。

$ pacmd list-sink                                               # サウンドデバイスの一覧を表示する
$ pacmd load-module module-combine-sink sink_name=combined slaves=alsa_output.pci-0000_00_1b.0.analog-stereo,MySink

sink_nameにはMySink同様sink名を指定し、slaveslist-sinkで得たnameセクションの値をカンマ区切りで指定する。

これによって新たにMySinkcombinedという再生デバイスが得られ、それぞれに対するmonitor出力の録音が可能になる。 virtual sinkを作らずにcombined sinkを作るだけで十分かもしれない。

なお、PulseAudioに関する知識に乏しいため、情報は不十分なものかもしれないことをご了承いただきたい。