先のシェルスクリプトを形にしました

一時キーボード無効

Temporary Disable Keyboard @GitHub

Xinputを使用してデバイスを無効/有効にするためのもの。

主な変更点は次の通り

  • 無効化を「時間制」「ダイアログ」「無限」から選択できるようにした
  • Zenityダイアログを若干調整
  • ランチャー用の.desktopファイルを追加

Zshスクリプトだが、case内で非常に珍しい;&(フォールスルーする)を使用している。

ターミナルエミュレータ選択機能

Terminal Selector @GitHub

主な変更点は次の通り

  • ランチャー用の.desktopファイルを追加
  • KDE Service用の.desktopファイルを追加
  • Nemo用の.nemo_actionファイルを追加
  • 対応する端末を大幅に増加
  • 利用できない端末を選択肢から除外するように変更
  • Zenityダイアログを調整
  • 柔軟に端末を追加できるようにファイルマネージャでの起動用の引数対応が連想配列で使用できるように変更

連想配列を使用するための方式は次のようなものだ。

わざわざ連想配列をテンプレート文字列とし、そこから配列に変換している理由は

  • 連想配列に格納できるのは文字列のみ
  • 置き換えしてからではDIRがIFSを含む可能性がある

【Linux複合技】 SSHポートフォワーディングしてセッションを維持しつつ多段SSHでファイル転送

SSHでリモートからポートフォワーディング

例えばNAT内に存在するコンピュータに対してサーバーに代理応答してもらう方法になる。

この方法を使えばNAT内のコンピュータに対してサーバーを経由してアクセスすることが可能になる。

このポートフォワーディングは以下のように行う。

-Lと比べ-Rはその意味を見失いやすい。

5000はリモートホスト側のポートであり、リモートホストのこのポートにアクセスすることによりローカルホスト側にアクセスすることができるようになる。

hostはローカルホストからみたポートだ。 sshを実行しているコンピュータ自身に転送するのであればlocalhostだし、LANの他のコンピュータ、例えばbobにアクセスしたいのならbobになる。

10000はhostのポートである。 ここではSSHに対してログインさせたいので、変更していなければ22になるだろう。

リモート側ポートはそのポートを開くため、1024より小さい値を指定するには特権がいる。 逆にホスト側ポートは単にそのポートに転送するだけなので転送したいポートを指定する。

このままだとログインしてしまうのでバックグラウンドで実行するオプション-fと、何もコマンドを実行しない-Nを組み合わせるのが一般的だ。

なお、-gをつけない限りはリモートホストではループバックネットワークインターフェイスにのみバインドされるため、リモートホストに対して外部からアクセス可能になるわけではない。

セキュリティを考えれば、公開はせずにSSHでサーバーにログインし、そこから転送するようにしたほうがいいだろう。

接続を維持する

このままでは環境によっては入出力がないSSHセッションはすぐ切断されてしまう。 そこで、このSSHセッションは維持してもらいたい。

ピンポンのための双方向入出力

結局使わなかったアイディア。

通常のシェルスクリプトではあるプロセスに対して別のプロセスが読むことも書くこともする、ということはできない。 そういうことがしたい場合の方法は主にふたつ。

Procfs

/proc/<PID>/fd/0に対して書き込めば標準入力に入力が与えられる。

このとき注意すべきは、標準入力がつながっているのが端末だと端末に書いてしまうので、標準入力はパイプにつながっている必要がある。 特にパイプから何も入れる予定がないのであればsleepにつなぐと良いだろう。

出力はパイプで受け取れば良い。

FIFO

こっちのほうが普通。 FIFOを使えばそこに書かれた出力を一括して受け取れる。

複数のプロセスが書く場合はちゃんと排他制御すること。 また、後処理を忘れないこと。

リモートがぽん

こんな感じでよかった。

pong.sh

readの-tオプションでタイムアウトしている。Zshスクリプト。

30秒ごとにPINGしていて、45秒間PONGが返ってこなかったら、たぶんコネクションは死んでいる。 まぁ、多分ぴんぽんする必要はないけど。(片方が送り続けていればいいはず)

ただ、死活チェックのために返してほしい。 どちらかといえば向こう側に送り続けてもらう必要がある。

コネクションが切れたら確実に死んでもらおう

こんな感じ。

もしくはこんな感じ。

Systemdでrespawn

systemdで起動させることにして、死んだら復活させてもらう。

[Unit]
Description=Connect for SSH port forwarding

[Service]
ExecStart=/home/jrh/bin/sshforward.zsh
ExecStop=/bin/kill -TERM $MAINPID
Restart=always

enableする予定はないので、Installは省略。

プロセスが死んだらRestart=alwaysなので復活する。 停止するときはユニットをstopすること。

ちなみに、KillModeを省略しているので、停止時にはsshもkillされる。

SSHの設定

SSHログインできるようにする

ここらへんは基本手順。

まず鍵の生成

$ ssh-keygen -f ~/.ssh/server_rsa

これを何らかの方法でサーバーの~/.ssh/authorized_keysに追記する。 ない場合は作成。パーミッションは600であること。

続いて~/.ssh/configに設定

Host server
  Uesr jrh
  Port 22
  HostName server.example.com
  IdentityFile ~/.ssh/server_rsa

これで簡単にログインできるようになった。

$ ssh server

こちらはログインする側の端末の設定である。

コマンド専用鍵を作る

まずは前項と同じように鍵を作って登録する。

転送は許可しないといけないので、こんな感じ。

authorized_keysのコマンド用鍵の行の先頭に以下のようなフィールドを追加する。

command="/usr/local/bin/pong.sh",no-pty,no-X11-forwarding

今回はno-port-forwardingしてしまうと動作しなくなる。 ポートフォワーディングと、標準入出力を使ったやりとりを行うためだ。

なお、この時SSH鍵を使用してアクセスした場合 コマンドは入れなくて良い。 そのコマンドしか実行できないので、勝手にそのコマンドが実行される。

なお、configファイルにはRemoteForwardの項目を入れるようにすると良いだろう。 次のように。

Host proxy-server
  User jrh
  Port 22
  HostName server.example.com
  RemoteForward 10000 localhost:22
  IdentityFile ~/.ssh/server-proxy_rsa

こちらはログインされる側の端末の設定。

多段ログイン

ログインする端末はサーバーにログインしたあと、SSHポートフォワーディングを利用してログインされる端末にログインする。 ログインする端末から見るとSSHを二度行うことになる。

もちろん、このようなことはできないわけではないのだが、これだとSCPやSFTPなどは利用しづらい。 また、できればコマンド一発で簡単にログインしたいところだ。

そこで、まずはログインする側の鍵をログインされる側に登録する。 これでまず、サーバーを経由せず直接に鍵認証可能な状態になる。

その上で設定ファイル(~/.ssh/config)にProxyCommandとしてサーバーのSSHを経由して接続する設定を記述する。

Host target-proxy
  user jrh
  Port 10000
  HostName localhost
  IdentityFile ~/.ssh/proxylogin_rsa
  ProxyCommand ssh -CW %h:%p server
  • Port-Rによってサーバーに開かれているポート
  • HostNameはサーバーにログインしてから接続するものなので、localhost
  • IdentityFileは直接のログインにも使用できるログインされる側に登録されているもの
  • ProxyCommandとして先程の設定に記載したHostの値を利用する

これで外出中でもサーバーを経由して端末にログイン可能になった。

複雑なので手順のまとめ

本文は知識順に記述しているが、ここではミニマムな達成順で記述する。

ここではログインする側の端末をlaptop、ログインされる側の端末をdesktop、サーバーをserverと呼称する。

  1. desktopで鍵を生成し、serverauthorized_keysに登録する
  2. laptopで鍵を生成し、serverauthorized_keysに登録する
  3. laptopで鍵を生成し、desktopauthorized_keysに登録する
  4. serverで動作するPONGコマンドを作成する
  5. server上のdesktopの鍵をPONGコマンドに結びつける。
  6. desktop上でserverに接続するためのコマンドを作成する。このコマンドは基本的に <PING> | <SSH> | <READ>
  7. desktopで作成したコマンドを反復起動するためのsystemdユーザーユニットを作成する
  8. desktop~/.ssh/configにコマンドに結びつけられたserverにログインする設定を記述する。ポートフォワーディングも記述する
  9. laptop~/.ssh/configserverへのログイン、及びdesktopに対してProxyCommandserverを通じてログインする設定を記述する

これで準備は完了。あとはdesktopでユニットを起動し、laptopからserver経由desktopログインのsshを実行するだけ。

おわりに

SSHの応用, systemdユーザーユニット, シェルスクリプト, 入出力とファイルデスクリプタ, procfs, FIFO, プロセスとシグナルなど一般デスクトップユーザーは触れずにいるような基礎知識が詰まったものになり、計らずもさながら中級Linuxer認定試験のような内容になった。

基礎に関する知識と理解があればこのように便利に利用することもできるので、 この記事がmagicalに見える方はぜひがんばって取り組んでいただきたいと思う。

【検索ワードに応えて】 ThinkPad X1 Carbon (2017, シルバー) のお話, Linux関連, その他

久しぶりの検索ワード反応企画。 ThinkPad X1 Carbon関連の検索が多かったので、併用されたワードに従ってコメントさせていただくことにする。

なお、ThinkPad X1 CarbonについてはYouTube (はるかみ☆ チャンネル)で開封動画を掲載させていただいているので、よかったらそちらもどうぞ。

また、そのほかLinux関連の検索にも回答させていただく。

ThinkPad X1関連

基本的なレビュー

ラップトップをガリガリ使うモバイラーなら持たない理由が見つからない。

XPS13のような13.3インチの中でも小型のものを除けばボディは13.3インチと変わりないサイズだ。 しかし14インチの画面は明らかに見やすく、作業もしやすいし、人に画面を見せるときにも良い。

そして非常に軽量でバッテリーマイレージも素晴らしい。 もちろん、キーボードはあらゆる現行ラップトップの中で最高だと思う。

唯一欠点としては天板の外板が弱い。 既に凹み、割れがある。それほど目立たないし、動作には問題ないのだが、ちょっとカナシイ。

買い時について

「高性能」「最先端」などを意識したい場合はリリース間もない頃が良い。

リリース直後は割引はなく、およそ半年程度で30%程度の割引になる。モデル末期は40%を越える程度の割引だ。

基本的にはThinkPadの場合30%程度割り引いた状態で競争力のある通常価格で、割引のない最初期というのはフリーク向けと考えられる。 なので買い時を気にするような人なら直後はないだろう。

春頃には30%前後の割引になっていたりするから(現時点でサイト公式のクーポンが28%、恐らくメルマガや店頭クーポンならもう少し行くだろう)、それぐらいが買い時ではなかろうか。

少しでも安く買いたい人は、翌年モデルが発表されてから決めるといい。 その頃にはかなり安くなっているし、在庫が残っていれば翌年モデルが出てからでも安く買える。 翌年モデルを待つべきかどうかの判断も出来てお得だ。

2017と2018に関しては、X1 Carbonとしての進化は微々たるものだったけれど、第8世代プロセッサになったという点がとても大きい。 ただ、私はかなり安く買えたので、そのタイミングでよかったと思う。

シルバーのThinkPadについて

良いと思う。

ThinkPadらしくないという批判はあるだろうけれども、マットだけれども黒のピーチスキンよりもサラッとした手触りで汚れもつきにくく目立たない。

シルバーのラップトップはそれなりに存在するので目立たないということは言えるけれども、「Hacker’s itemたるThinkPad」と「美しくおしゃれな高級ラップトップ」を両立させる意図は十分に達成できている。

控え目にいっても最高にかっこいい。

国産と中国産について

何も違わないから安心してほしい。 400万円するようなP920でも中国産だ。

なお、納期はかかる。X1は予定納期よりも遅かったという人が珍しくないようなので注意してほしい。

その他の検索ワード回答

シェルスクリプトの並列実行

基本的な形式は次のとおり

シェルスクリプトの並列実行は待ち合わせず投げっぱなしにするのが基本。

ただし、どうしても待ち合わたい場合はwaitを使う方法もある。

とした時、$!でサブシェルのPIDが取れるので、

としておけば待ち合わせる必要があるタイミングで

とすることができる。これはBashでもZshでも共通。

入出力をやりとりするのであれば、下流のパイプに流すべきで、親プロセスが出力を披露ようなことは考えないほうがよい。

どうしてもであればファイルに書いてwaitするか、もしくはZshならProccess Substitutionを使用する。

あるいは大量の処理があり、複数のワーカーを走らせたい場合はflockを使うのが無難だろう。 例えば以下のようにする。

要点は以下の通りだ。

  • 関数workerが各ワーカーが実行する内容
  • これをサブシェル内でworker nの形で実行する
  • ファイルデスクリプタはクローンされるので、標準入力から読んだ場合、親シェルもサブシェルも同じものを読み進めるし、位置も同時に変化する
  • しかし、もし同時に読んでしまうとおかしなことになるので、読んでいる間は他のシェルに読んでもらっては困る
  • そこでロックファイルを作り、これをロックすることで排他制御する。いわゆるドットロック。
  • exec 9>| .lockでファイルデスクリプタ9番をロック用に確保
  • 開きっぱなしになるので、flockでこのファイルをロック
  • ロックを獲得できたら標準入力から読む
  • 読み終わったらファイルデスクリプタを閉じてロックも解放
  • これでキューから1行読めたので、処理を進める
  • 「1行では足りないよ!」という場合、エントリをファイルに書いておいてディレクトリにまとめ、キューはファイル名にするとかすれば良い

AMD APU (Godavari/Kaveri) と Linux

特に問題はない。

以前はCatalystドライバのおかげでずいぶん苦労させられたけれども、 AMDGPUになって以来目立った問題は発生していない。

割と電気を食うけれど性能は微妙なので嬉しくはないと思う。 コストパフォーマンス的にみれば、これくらいの性能がおいしいという人は多いと思う。 ビデオ関連も充実しているし、Killerシリーズなんかは機能も充実しているしね。

XMPP

ちょっと話題が広すぎて何を求めているのかがわからない。ごめんよ。

DPI

これかなり広い。

LinuxでのHi-DPIの話なら/etc/X11/xorg.conf.d/以下にモニターの設定ファイルを書く。 40-monitor.confとかで。

Section "Monitor"
    Identifier             "<default monitor>"
    DisplaySize            286 179    # In millimeters
EndSection

で、KDE Plasmaを使うといい感じになる。 Plasmaを使わない場合については、Qtアプリケーションについてはなんとかなるけれど、GTKに関してはうまいことスケールしない。

LightDMに関してはGreeterの設定ファイルにxft-dpi=と書きましょう。

Hi-DPIはLinuxでは結構苦手にしている感じ。

フォントの設定はまた別。

某人物について

コメントする気はありません。

VP9のハードウェアエンコード

  • Intel QSVを使ってください
  • LinuxならVA-API経由ffmpegが良いよ
  • ただし画質は絶望的だったとは言っておく

Intel QSV * H.265

  • LinuxならVA-API経由ffmpeg
  • 速度はそこそこ。X.265とは雲泥の差。CPU負荷は0ではないというか、普通に40%くらいはいく
  • ちゃんとVA-APIドライバ入れようね

scale_vaapi

VA-APIを使用する場合の出力画面サイズ指定。 変更しない場合は省略して大丈夫。

AMD VCE / NVIDIA NVENC

VCEはLinux的にはVA-API経由。なのでQSVと一緒。

ただし、AMDのビデオドライバはVA-APIだけじゃなくVDPAUも使える。 ところがVA-APIがエンコード/デコードなのに対してVDPAUはデコードのみ。

VA-APIをVDPAUに転送するドライバ(libva-vdpau-driver)と、VDPAUをVA-APIに転送するドライバ(libvdpau-va-gl)があり、 VDPAUを有効にして、VA-APIに転送するドライバを使ってしまうと(Nvidiaの場合はVA-APIが使えないのでこうする)デコードのみになってしまって使えない。

ちゃんとlibva-mesa-driverを使いましょう。

Nvidiaの場合はVA-APIをサポートしておらず、VDPAUはエンコードができないので、 NVENCは専用のインターフェイスになっている。

どっちが優れているというのは難しいけれど、Nvidiaのほうが対応フォーマットは多い。

DiscordとSlack

基本的にはDiscordがいいと思うし、最近はSlackも微妙だと思うのだけれども、「両方あると嬉しい」という面もある。

Discordの場合「ユーザーという概念がある」ということが大きい。

Discrodでつながると、どのようなつながりであれ、「その人」というのが見えてしまう。 Discordは通知をカスタマイズできないため、「通知をオンにしている全ての人からの通知が一律に行われる」ということになる。 棲み分けをする方法がない。

これはLINEと同様の問題である。 恋人だろうが、ゲーム仲間だろうが、仕事の人間だろうが、区別する方法がないのだ。 アカウントの切り替えは難しいためアカウントで分けるのも現実的ではないし、アカウントで認識されているから一時的な連絡先にもしにくい。

Slackの場合はやりとりもつながりもあくまでそのチーム内でのことなので、仕事の関係などであればSlackのほうが便利だ。

自前メールサーバーからのメールをGMailが受け取らない

主にはホスト認証の関係。

GMailは送られてきたメールサーバーが、本当にそのメールを送る資格があるかをチェックする。

設定方法はいくつかあるけれど、SPFレコードを書くのが楽。 「メール SPF」で検索すると色々出てくる。

LinuxとRealTek ネットワークカード (RTL8152ほか)

ASIXよりはマシだけれど安定して苦しめてくれるRealTekのネットワークカード。

Linuxではネットワークアダプタは

Intel > Atheros (Killer) > Broadcom > RealTek > Asix

だからね。

RealTekのWiFiモジュールであるRTL8152のドライバはカーネルモジュールとしてある。 Arch Linuxの場合はDKMSになっていて、AURからインストール可能。 場合によってはRTL8153をブラックリストに入れる必要がある。

インストールしなくても動作はするけれど、うまく交信できなくなったりする。 安定性の面から言えば入れるべきだけれど、入れたところでうまくいかない場合もある。

「うちのディストリビューションにはないよ!!」という方。 Archにおいで。むしろManjaroにおいで。

ffmpeg * V4L2 と Logicool C270 で HD 30FPS 撮りたい

まずffmpeg * V4L2 でウェブカム撮影する方法は次の通り。

デバイスは適宜読み替えること。

NVENCでG.265に変換して変換して保存する場合は

QSVやVCEでVA-APIを使う場合は

さらにPulseを使って音も入れる場合は

HEVC+Opus MKVが最近のお気に入り。

そしてビデオサイズを指定する場合は

しかしLogicool C270だとこれで5FPSになってしまう。かっくかくやでぇ。 そこでフレームレートを指定する。

けれどこれでも7.5FPSになってしまう。 v4l2-ctlを用いて確認してみる。

YUVU以外にMotionJPEGもサポートしている、と。 で、詳しく見てみると…

% v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Index       : 0
        Type        : Video Capture
        Pixel Format: 'YUYV'
        Name        : YUYV 4:2:2
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x176
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 432x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 544x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 640x360
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 752x416
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x448
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 864x480
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x544
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x720
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1024x576
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1184x656
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.133s (7.500 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.133s (7.500 fps)
                        Interval: Discrete 0.200s (5.000 fps)

        Index       : 1
        Type        : Video Capture
        Pixel Format: 'MJPG' (compressed)
        Name        : Motion-JPEG
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x176
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 432x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 544x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 640x360
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 752x416
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x448
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 864x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x544
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x720
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1024x576
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1184x656
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)

YUVUだと720Pは5/7.5FPSしか選択肢がない。 一方、MotionJPEGであれば30FPSでもとれるらしい。 720Pのカメラ、とあるのだが、何気に1280×960などというフォーマットもあるのは、センサー自体が4:3だからということだろうか。

というわけでmotionJPEGを指定する。

しかし、大量のエラーメッセージが出る

[video4linux2,v4l2 @ 0x5600641ec760] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
[mjpeg @ 0x5600641eea00] unable to decode APP fields: Invalid data found when processing input

しかも、画質は非常に悪い。 確かにHDで30FPSを取るという目的は達成できたけども、画質を考えると普通に640×480で取るのと大差ないという悲しさよ。

MotionJPEGで高画素で取るのなら一旦はMotionJPEGのままでもよさそう。

調べた限り、USB3.0接続のウェブカムというのはなさそうで、 H.264でFHD 30fpsの出るウェブカムというのはあるにはあるけれども、UVC1.5に対応していないとなかなか面倒なことになる…と

手頃にH.264が取れるウェブカムとしては、ELPのカメラモジュールがあったりするのだけれど、 ウェブカムに色々求めてはいけないということなのだろうか…

Linuxでキーボードをつないだまま掃除したい

キーボードが汚れているなぁ、と気づいたとき、あるいはキーボードがべたつくとき、キーボードを掃除したいけれど電源を切りたくないということはないだろうか。 特にデスクトップの後方につないでいる場合や、ラップトップの場合にはキーボードを外すのも面倒な話だ。 スリープにしてもキーボードに触ったら復帰してしまうし、なかなか厄介だ。

そこで一時的にキーボードをつないだまま無効にする方法を考えてみた。

キーボードを無効にする方法としてはXによるデバイス認識であればxinputが利用できる。

次の方法で認識されているデバイスを確認する。

あまり見やすくはない。

⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ ELECOM ELECOM UltimateLaser Mouse         id=9    [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Power Button                              id=7    [slave  keyboard (3)]
    ↳ FCL USB Keyboard                          id=8    [slave  keyboard (3)]

キーボード全体をオフにしてしまうと困るかもしれない。 なので、Virtual core keyboardをオフにすることは思いとどまったほうがいいだろう。

FCL USB Keyboard(idは8)を無効にするには次のようにする。(手前側の8がID、後のほうは固定の値)

有効に戻すにはこうだ。

外付けキーボードが他に用意できるならいきなり無効にしても構わないが、そうできない場合は時間で復帰するようにしたほうがいいだろう。

安全のためアプレットから復帰できるようにするほうがいいだろう。 マウスで操作できるよう、Zenityを使ってon/offできるようにした。 また、off時にはタイマーをかけることもでき、タイマーをかけない場合は確認される。

Gistで公開している。 Zshスクリプトであり、実際にZshの機能を使用しているのでBashでは動かない。 Zenityはなかなかコマンド置換が難しく、(f)は欠かせない。

昨今のブラウザ事情

ウェブブラウザとウェブテクノロジー

今やウェブブラウザは中核的ソフトウェアといって過言ではないだろう。 世界はウェブを中心に回っているのが現実だ。

だが、それは問題をふたつもたらしている。

ひとつは、過当競争だ。

あまりにもウェブに依存しすぎているがために、ウェブが高度技術化し、開発コストも増大しとてもついていくのが困難になっている。 現状ウェブ開発をリードしているのはGoogleであり、ChromiumによるBlink/V8エンジンが最も進んでいる状態だ。 これに対抗するのはMozillaのGecko/SpiderMonkeyで、Chromiumよりも進んだ実装を行うこともないではないものの、現実にはFirefoxに実装されChromiumに実装されない機能は大概標準化されないのが現実だ。 (ただし、標準化においてはある程度Mozillaが主導権を握る展開が続いている)

MicrosoftによるEdgeHTMLはこれと比べて明確に遅れをとっている。 これはちょっとした理由がある。 そもそもEdgeHTMLはWebKitをターゲットとしているのだが、WebKitは現代ではとてもではないが使い物にならない。

WebKitを開発しているのはAppleだし、そもそもWebKitはSafariのものなのだが、WebKit自体はオープンソースだし、他のソフトウェアも利用することができる。 とはいえqtwebkitに関しては既に廃止となっており、WebKitのバージョンも古い。

WebKitとBlinkを比べる良い手段はMidoriとFalkonを使用することだろう。 MidoriはAppleがcommitするWebKitGtk+を使用しており、一方Falkon(かつてのQupzilla)はBlinkを使用するQtWebEngineを使用している。 そして、Falkonで表示に困ることはないのだが、Midoriでは普通に「表示できないサイト」や「利用できないサイト」が存在するのだ。

根本的にWebKitはカジュアルでライトなウェブブラウジングに的を絞っていると考えて良い。 つまり、ちょっとした調べ物などであり、完全に表示できることよりも軽快であることを望むためのものであり、実際Safariは機能的にかなり限定的である。 最小限の機能を搭載することからも「ちょっとした行為」であり、目を尖らせてに向き合うものではないと考えているのがわかる。

実際、Microsoft Edgeもそのような考え方であり、機能的に貧弱だったInternet Explorerと比べても機能はさらに削られており、メニューは実に寂しい。

生殺与奪を握られたウェブエンジン

だが、この問題はなかなか複雑だ。

AppleとGoogleはこれらウェブエンジンを「自由に使わせなければならない」呪縛にとらわれている。

これはもともと、Appleが既にある程度成熟していたウェブエンジンに参入するにあたり、スクラッチから開発することをよしとせず、KHTML/KJS Softwareをベースにすることを選択したことある。 当時のKHTMLはLGPLだったので、ここから派生するためにはLGPLを継承せざるをえなかった。 もちろん、そのWebKitから派生したBlinkにしても同様にLGPLを継承するしかない。これにより望む望まざるに関わらず「開発したものは配布するためには公開し自由を保証しなければならない」ということになったのだ。

そのため均衡が保たれているのだが、実際技術標準というか、「ウェブの世界」そのものは主にはGoogle、そしてAppleの意向は完全に反映されるのであり、 世界をウェブが支配している以上世界の支配者として君臨する状況を許してしまっている。

これは、GoogleやAppleが「採用する」と決めた方針に反する方法がないという問題だ。 LGPLである以上、ウェブブラウザを「秘密」にしてしまったり、伏せられた邪悪な機能を搭載するのは難しい。 だが、正式にプライバシーを侵害するような機能、仕様を採用すると決定したとして(既にそのようなものがなくもないが)、それを覆すことができない。 もちろん、フォークするという選択肢はあるが、ウェブブラウザの規模と進歩を考えるとGoogle並の開発力で追従するということは現実的ではない。 結局のところ誰もがGoogle, Mozilla, Apple, Microsoftの少なくともいずれかには従わなければならないという状況にあるのだ。

実際、Chromeユーザーでも「Google及びChromeに対する信頼度」はかなり低いというアンケート結果がある。

唯一の良心といえるのがMozillaだが、Mozillaの体制や行動がプライバシー上の理由で批判されたことは一度や二度ではない。

結果的に我々の生殺与奪は彼らに握られているというのが現実であり、 そして現状においてはそれを覆すほどのリソースはどこにもないのだ。 これはOperaのような老舗ブラウザ屋がBlinkを採用し、WebKitの祖先であるKDE ProjectがQtWebEngineを採用していることからも明らかだろう。

セキュリティとプライバシー

もうひとつの問題はウェブを侵食するプライバシーの問題だ。

セキュリティについて昔と比べることは意味がない。

昔はセキュリティを脅かすものは見るからに怪しげな「悪人」であり、「怪しげなものを遠ざければ良い」というものだった。 また、そのようなセキュリティ上の問題は「プライバシーの問題」ではなかったのだ。

ところが現代においてはサービスを利用する上でプライバシーを侵害されることは前提であり、 それどころかウェブブラウザを利用することによってもプライバシーが侵害されるという状況にある。

なぜこのような状況になるのか。

まず、Facebookを筆頭にして、現在はプライバシーが主要な商品となりすぎていて、 どこもかしこもプライバシーを欲しがるという現状がある。 これはウェブの技術如何に依らず根本的な問題である。 「プライバシーを侵害したいと思う人がいなければプライバシーを侵害するものが作られることはない」のだから。

だが、彼らウェブブラウザデベロッパー達はこれらの「プライバシーを侵害したい」という要求に応えているし、 また彼ら自身がプライバシーの侵害を望んでもいる。GoogleやAppleが過剰かつ積極的に個人情報を収集している状況を忘れてはいけない。

我々は日々普通に使っているだけでも著しくプライバシーを侵害され続けている状況にあるのだ。

プライバシーを取り返せ

中には完全にプライバシーを保護するブラウザもなくはないが、代償は大きい。 そうではなく、普通は求めているのは「与えて良いと判断して選択し許可した以外のプライバシー侵害は認めない」というものだろう。

だが、これはなかなか難しい。 ウェブブラウザの根本的な機能として既にプライバシー侵害を可能にする機能が組み込まれているからだ。 例えばComodo Dragonはプライバシーを重視しているということだが(PrivDog事件もあったが)、トラッキングなどは普通に行えてしまう。

また、Vivaldiもプライバシーを重視しているが、それでも問題になっているプライバシーはあまり解決しない。 裏側で悪意ある行動をとっていないというだけで、知られないうちに何かが行われることを防いでくれるわけではないからだ。

ある程度、そして確実に効果がある方法は「セッションを残さない」ことだ。 トラッキングが最も驚異なのは、「アクティビティが同定でき」「蓄積されるから」だ。 蓄積されなければ同一人物なのか否かを特定することは困難になるし、取得可能な状況はある程度限定的になる。

Chromiumならば次のようにすれば最初からプライベートモードになるし、使うたびに情報はクリアされ、ある程度安心だ。

chromium --incognito

もちろん、これでTwitterとGoogleとFacebookに同時にログインしたら台無しである。 そんなことはせず、他のサービスを利用するときは必ずブラウザを閉じて行うべきだ。 これは、ログインしなくても、サイトごとにセッションを切るべきである

Vivaldiも--incognitoオプションを受け付けるため、Vivaldiを使えばさらに(いくらか)安全になる。 Linuxにおいてはデフォルトブラウザとして--incognitoつきでVivaldiを起動するようにしてしまうといい。 以下は私が使用している$HOME/.local/share/applications/incogvivaldi.desktopファイルだ。

[Desktop Entry]
Version=1.0
Name=Vivaldi Incognito
# Only KDE 4 seems to use GenericName, so we reuse the KDE strings.
GenericName=Web Browser (with Incongnito)
GenericName[ja]=ウェブブラウザ (with Incongnito)
Comment=Access the Internet (with safety)
Comment[ja]=インターネットに安全にアクセス
Exec=/usr/bin/vivaldi-stable --incognito %U
Terminal=false
Icon=vivaldi
Type=Application
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml_xml;image/webp;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
Actions=new-private-window;

[Desktop Action new-private-window]
Name=New Incognito Window
Name[ja]=新しいシークレット ウィンドウ
Exec=/usr/bin/vivaldi-stable --incognito

デフォルトの.desktopファイルとの違いは以下の通り

  • 起動時に--incognitoオプションを付加
  • 日本語と英語のみにし、翻訳を排除(どうせ読めないし、ローカル設定だし)
  • new-windowアクションを除去し、デスクトップの右クリックメニューもIncognito限定に

これで開くアプリケーションの選択肢としてVivaldi Incongnitoが追加される。

プライバシーを強化する設定やプラグインを追加すればより万全だろう。

いちいちセッションを切るのは面倒だ、というまっとうな意見のために、私はMy Browser Chooserというソフトウェアを開発している。 サービスごとにプロファイルをわけてしまえば、サービス側がプロファイルを横断しての情報収集はできない。 運用ポリシーさえ守ればだいぶ楽になる。Zshスクリプトなので、Unix的な環境においてのみ機能する。

危ういスマートフォンブラウザのプライバシー

パソコンなら(特にLinuxならば)このようにいくらかの解決策を提示できる。 だが、本当に厄介なのはスマートフォンだ。

スマートフォンの場合ブラウザが握ることができる情報はパソコンの比ではない。 だが、にもかかわらずユーザーに与えられるコントロールは極めて少ない。

スマートフォン的な設計思想として、「可能な限りコントロール部品を減らす」というものがある。 例えばMicrosoft Edgeはメニューボタンがハンバーガーメニューになっておりドロワー式だ。これはタッチデバイス向けの設計であり、GNOME3もまた同様の設計になっている。 ドロワーに含まれるメニューも少なく、ここまでメニューを減らしているのは当然に相応に機能自体を削っているということである。 機能が多ければそれだけなんらかの煩雑さを持たざるをえないからだ。

このような設計にしている理由はふたつある。

ひとつはスマートフォンの狭い画面での煩雑性が操作性の低下に直結するためだ。 そして、もうひとつはユーザーが馬鹿でいられるようにである。

私はこのような考え方は好きではない。 なぜパソコン用のソフトウェアが低機能なスマートフォン設計を採用せねばならないのか?

このコントロールの少なさがプライバシーの問題にも直結している。 現在では必須ともいえるプライベートモードがひどく軽視されているし、ページを開く時点でプライベートモードで開く選択肢を与えられない。 スマートフォンはパソコンよりもアプリからリンクを開く機会が多いにもかかわらずだ。

もちろん、プロファイルの切り替えもサポートされていない。 結果的にスマートフォンに蓄積された情報が簡単に抜き取られてしまう状況である。 なお、ブラウザを使い分けたところでAndroidならば多くのブラウザはAndroidのWebEngineを使用しているため、中身はひとつ、結局は使い分けに意味などない。 iOSについてはあまり知らないが、おそらくは似たようなものだろう。自前でのウェブエンジン実装はあまりに困難だからだ。

ひどい話だと思う。 だがAndroid WebEngineとはつまるところBlinkであり、なかなか太刀打ちできるものではない。

使い分けるのであれば、Mozilla FirefoxとMicrosoft Edge、そしてBlink系ブラウザ(Chrome, Operaなどだ)を使い分けるという方法だ。 数が少ないのであまりリスク軽減はできないが、いくらかマシな方法だろう。

元は表現力も機能も安定性もひどいものだったAndroid Firefoxだが、現在はかなり改善されており、十分実用になる。 Quantam(Firefox 57以降)をもてはやす記事ほど素晴らしいものだとは思わないが、「Firefoxが実用になる」しいうのは極めて喜ばしいことだ。

それよりも推奨できるのはFirefox Focusを使用することだ。 Firefox Focusは常時プライベートモードのFirefoxである。firefox --private-window相当ということではなく、プライバシー保護のためにかなりenhanceされている。 ほとんどのブラウジングにおいてはFirefoxで困ることはなく、またアクティビティを保存する必要もない。 そして、Mozillaによって提供されるFirefox FocusはCM Security Browseなどを使うよりもよっぽど信用できると言える。

そう、ブラウザは重大なプライバシー資源となっているために「信用できるか」が極めて重要なのだ。 ましてスマートフォンブラウザならなおさらで、プライバシーの塊であるスマートフォンを狙ったアプリなど数知れずある。 言ってしまえば大部分は怪しいし、よほど信用できない限りは使えないのが現実である。 ブラウザはその基本的な動作においてほぼ全権を要求するという点も大きい。正常に動作させるために権限を与える必要があるためにリスクが高いソフトウェアなのだ。

言い換えれば、悪意ある人からすれば「これはブラウザです」というふうに言っておけば

スマートフォンブラウザの機能にも不満

典型的なのはOperaで、Operaは以前はかなり高機能なブラウザであった。 PCブラウジングやページ保存、印刷機能も備えていたのだ。

ところがそれらの機能は現在はもうない。スマートフォンには必要ないと判断されたのだろう。 だが、実際はOperaはもはや必要な機能が削除されてしまって使い物にならない。 このような「スマートフォンだから」という言い訳は、一体スマートフォンだからなんだというのかと思うほどに理由になっていない。

表示の難しいinspectionなどはまだしも、印刷、ページの保存、文字エンコーディングの選択、プラグイン、ページ検索、 ローカルファイルの取り扱いなどがスマートフォンにおいて欠けている必要があるのだろうか? それ以外にもウェブブラウザが様々に豊富な機能を備えているにもかかわらず、スマートフォン版ではない、あるいはコントロールする手段が与えられていない。 なぜスマートフォンではユーザーからコントロールを剥奪するのか。理解し難い。

Vivaldiのようなブラウザをスマートフォンに最適化させたようなものは出ないのだろうか。 一応、Vivaldiのスマートフォンバージョンの開発は行われていはいるようだが。

Intel QSV * Linux * FFmpeg * (H.265|VP9)

Intel QSVによる動画エンコーディングを試してみた。

LinuxにおいてIntel QSVはVA-APIを通して利用することができる。 そのため、FFmpegのVA-API機能を使用してエンコードしてみる。

VP9 WebM。

おおよそ基本的なフォーマットに従っているけれども、注意点は-vfオプションだろう。

これはビデオフィルタを指定するのだが、この中でscale_vaapiは動画の画像サイズ(よく解像度と言われるもの)を変更している。 これは、ソフトウェアエンコーディングのものと比べ柔軟性が劣るため、スクリプトで連続処理する場合はよく考えて設定する必要がある。 特にアスペクト比が一定でない場合は注意が必要。

VP9でconstant qualityエンコーディングしたいと考えたのだけど、結局まともな結果は得られなかった。 -qだろうが-qpだろうが、設定は基本的に無視される(もちろん、-b:v 0しているのだけど)。

H.265の動画を作る。

そして、-qp 32のH.265なMP4と、-b:v 2.5MのVP9なWebMの比較が次の通り。

-rw-r--r-- 1 aki aki  43215798  1月 24 14:27 _comp_fuwa.mp4
-rw-r--r-- 1 aki aki  43365795  1月 24 14:30 _comp_fuwa.webm

VP9は非常に荒れている
VP9 2.5Mbps キャプチャ

H.265は良好な画質
H.265 2.5Mbps (qp=32)

VP9のほうは、とても見られたものではない。 オリジナルは171484771バイトのH.264 MP4であるが、

encoder         : Lavf57.25.100
  Duration: 00:02:14.08, start: 0.000000, bitrate: 10231 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, smpte170m/unknown/smpte170m), 1080x1920 [SAR 1:1 DAR 9:16], 9942 kb/s, 29.88 fps, 29.88 tbr, 15296 tbn, 59.75 tbc (default)

H.265のほうがなんら問題なく見られるのに対して、VP9のほうはちょっと実用に耐えない。 フリーのコーデックを使いたいという気持ちは強いので、何度も実験しているのだけれども、今のところ「高圧縮のH.265並の圧縮度を求めるとひどい結果になる」という結論しか得られていない。

そもそも(VP10が合流した)AV1が「HEVCに迫る」なんて言っている状況を鑑みればそんなものなのかもしれない。 AV1はまだavcodecには載っていないので、WebM勢は遅れが目立ち、このままではWeb配信のみのフォーマットになってしまいそうだ。

WebPが後発のHEIFに飲み込まれそうな情勢を考えても、世界はライセンス問題という頭痛の種をなんとかしようという方向には進まないらしい。

個人的に所蔵するデータについては、恐らくおとなしくH.265/MP4にするのが無難だろう。 公開・配布する場合はVP9も選択肢に入るだろうし、その場合はIntel QSVでエンコードできるのは非常に嬉しいだろう。1

先日のNVENCを使用する方法(Nvidia版, H.264)は次のようなものだった。 どちらかといえばVA-APIにして欲しいなぁ…


  1. 自分で所蔵する(オリジナルになる)特別な動画データなら時間をかけても構わないが、一時的な自分ではあまり使わないデータであれば瞬間で終わってほしいと思うのが人情だろう。

ConoHaへのサーバー引っ越しレジュメ (DeleGate-Nginx/Postfix/Dovecot, Let’s Encrypt)

概要

作業概要は以下の通りだ

  • サーバーをDTI(@ServerMan)からConoHaに変更する
  • サーバーOSをCentOS (6.9)からArch Linuxに変更する
  • WebサーバーをDeleGateからNginxに変更する
  • WebコンテンツシステムをPureBuilder2からPureBuilder Simplyに変更する
  • Mimir YokohamaのWebコンテンツを別サーバーのWordPressから新サーバーのPureBuilder Simplyに変更する
  • Webメニューを完全JavaScriptフリーにする
  • Postfix/Dovecotを引っ越しする
  • DNSサーバーをConoHaとし、DNSの設定を変更する
  • 一部のドメインを廃止とする
  • 一部のドメインの役割を変更する
  • Let’s EncryptによるSSL証明書を取得し、HTTPSに対応する
  • 同証明書にメールも対応させる

なお、あまり詳細な解説はしていない。 Linuxやサーバーに関する基本的な事項に対して理解していないまま実施するのは危険であるため、 「コピペ仕様」にはしていない。 詳細に対してエラーが生じるなどの理由でより情報が欲しい場合はあるだろうが、 「言っていることが理解できない」のであれば、サーバー構築をするにはまだ危険なレベルにあると思ったほうが良いだろう。

承前: 開発

PureBuilder Simplyの開発

今回のために新しいコンテンツシステムであるPureBuilder Simplyを開発した。 この詳細は別に譲ろう。

テンプレートの開発

PureBuilder SimplyはPandocテンプレート+eRubyテンプレートというテンプレートを扱うことができる。 PureBuidler Simplyにテーマファイルがあるわけではないので自分で書く前提である。

今回は複数の表示デザインがあるのだが(現在のところは表示されるのはアーティクルモードとプロモーションモードの2つだけだが)これは全てPandocテンプレートとCSSで実現している。

もちろん、このようなテンプレートの開発はWeb屋の腕の見せ所だろう。

CSS

サイトはそれほど華やかなデザインではないが、技術的に劣っているわけではない。 その最たるものがCSSのみで書かれたハンバーガーメニューとドロワーだろう。

ポイントを簡単に言うと

  • ドロワーはfixedで上部に最初からある。display: noneで、高さは比較的新しい単位であるvhである
  • ハンバーガーメニューはtransitionを使っている
  • z-indexでメニューのほうが上になるようにする
  • 状態変遷は次のような方法でコントロールしている
    • 表示されないチェックボックスを用意し、操作対象をlabelで関連づける。これによりlabelで囲まれた要素をクリックするとチェックボックスがトグルする
    • CSSの+セレクタは同じ親要素を持つ次の兄弟要素に適用される
    • チェックボックスにはチェックが入っているときに適用される疑似要素:checkedがある
    • そこで、チェックボックス本体の直後に対象となるセクションコンテンツを置くことでチェック状態によって状態をトグルできる
    • ドロワーはfixedなのでどこに書いても構わないので、このセクションコンテンツの中におく。場所としてはメニューの位置に基づくのが良いだろう

見た目はWordPress時とあまり変わっていないが、性能は大幅に向上した。

速度

キャッシュの効かない初回アクセスで従来のWordPressページが5.57s、新しいページは約400msと10倍程度高速化した。

ConoHaサーバーのスタートアップ

立ち上げ

ConoHaのサインアップは10分もあれば可能で、即座にサーバーを使いはじめられる。

サーバー仕様は東京リージョンの1GBプランである。

512GBプランは安いが、性能が十分でなく、またマイグレーションができないため、1GBプランとしている。

この時点でサーバー選択が可能なので、Arch Linuxを選択する。 また、この時点である程度のセットアップが可能だ。 ここでSSH公開鍵の登録が可能である。

のようにして専用に生成しておく。 そしてconoharoot.rsa.pubを登録する。 名前からもわかるように、ここで登録する鍵はroot鍵である

また、開放するポートも選択できる。 ここで開放するポートはサーバーよりも上流でフィルタリングされる。 ここで透過していないポートに対するアクセスはサーバーに到達しない。

ただし、結果的にSSHポートの変更はサーバーに負担がかかるものになっている。 少なくともパスワードログインは禁止すべきだろう。

現時点ではSSHのみを通過させる。

初期設定

ConoHaのArch Linuxは標準インストールではなく、ある程度調整されている。 主にSSHログインが可能で、SSH公開鍵が登録され、パスワード認証不可となっている、といったことだ。 こうした内容は/etc/cloud/conoha-init/conoha-init.shによって確認可能だ。

複数のサーバーを接続する予定であれば変更すべき点は多いが、そうでなければ作業は平凡だ。

アップデート

まずはアップデートする。 20MB/sも出るため、超早い。

Zsh

私としてはZshがないと話にならないので入れておく。

これ移行はZshでの作業

一般ユーザーの追加

もちろん、一般ユーザーは登録されていない。

この時点で一旦再起動しないとパスワード設定ができないので、再起動しておく。

パスワードの設定

その上でvisudoを使って%wheelに対するsudoを許可する。

pacaurとyaourtのインストール

AURパッケージも扱う予定であるため、pacaurを入れておく。

# su - jrh
% gpg --recv-keys 487EACC08557AD082088DABA1EB2638FF56C0C53
% sudo pacman -S git

%git clone --depth=1 "https://aur.archlinux.org/cower.git"
%cd cower
%makepkg -si
%cd ..

%cower -d pacaur
%cd pacaur
%makepkg -si

これでAURからのパッケージインストールが可能になったので、Yaourtを入れておく。 作業が明確に自動化されていたり、システマチックに行えるのならYaourtはいらないかもしれないが、 まとめて検索するためには欲しい。

% pacaur -S yaourt

必要なソフトのインストール

ここでいう「必要なソフト」は私の取り扱い上の話だ。

% yaourt -S ruby openbsd-netcat rsync mercurial postfix dovecot nginx fcgiwrap certbot certbot-nginx vim

一般ユーザーでの鍵ログインの準備

サーバーで受け入れの準備をする

% mkdir .ssh

ローカルで鍵を生成しておく。

% ssh-keygen -f ~/.ssh/conoha.rsa

~/.ssh/configに設定する。 これは名前によるアクセスを可能にするためである。 (同一ホストに対する異なる鍵でのアクセスのため、鍵を指定せずに済むようにでもある) もちろん、読み替えること;

Host conoha-root
  User root
  Port 22
  HostName conoha.site.static.cnode.io
  IdentityFile ~/.ssh/conoharoot.rsa

Host conoha
  User jrh
  Port 22
  HostName conoha.site.static.cnode.io
  IdentityFile ~/.ssh/conoha.rsa

rootでは作業できるので、転送する。

% ssh conoha-root 'cat > /home/jrh/.ssh/authorized_keys' < ~/.ssh/conoha.rsa.pub

サーバー側でパーミッションの設定を行う

% sudo chown -R jrh:jrh .ssh
% chmod go-a -R .ssh
% chmod go-a .

そしてsshdリロード

% sudo systemctl reload sshd

DNS設定

ドメインを複数持っていない場合はいきなり完全移行できなかったりするので、 一時的にサブドメインを作るなどする必要がある。

ConoHaコントロールパネルのDNSからDNSの設定を行う。 (DNSの設定ってなんだ、という者はサーバーを立てるにはまだ早い。修行してくるべし)

これは本番サーバーのものを含む。 ただし、稼働中の本番サーバーのアドレスをこの時点で変更してはならない

そして、DNSサーバーをConoHaのものに変更する。

今回の場合従来はドメインサービス提供のDNSを使用していたため、同サービスのメニューから変更を行った。

WebとLet’s Encrypt

Nginxの立ち上げとテスト

従来がDeleGateで、Nginxにするため互換性は全くない。

Nginxは単純にstartすればアクセス可能な状態だが、移行のための準備をしていく。

まずは、Archの記述に合致するようにserver-avilableディレクトリを読むようにしたほうが良いだろう。

http {
    include       mime.types;
    include       /etc/nginx/servers-avilable/*;
    ...
}

これで/etc/nginx/server-avilableを作ればそこに配置したファイルを読むようになった。 この時点でrestartすると…

Dec 19 18:45:42 archlinux nginx[9339]: 2017/12/19 18:45:42 [warn] 9339#9339: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size

とのことなので増やす。

http {
    include       mime.types;
    include       /etc/nginx/servers-avilable/*;
    default_type  application/octet-stream;

    server_names_hash_bucket_size       128;
    types_hash_max_size                 4092;
    ...
}

配置するファイルはArchwikiに従ったもので大丈夫だ。

server {
  listen 80;
  listen [::]:80;
  server_name domain.tld;
  root /usr/share/nginx/html;
  location / {
    index index.htm index.html;
  }

  # ACME challenge
  location ^~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/lib/letsencrypt;
  }
}

domain.tldは適切なドメインに置き換えること。

ここで、あまり書かれていない重要なこと。

rootというのはドキュメントルートで、locationの起点となる。 つまり、

location /foo {
  root /usr/share/nginx/html;
}

であるとき、/foo/bar.htmlにアクセスすると読まれるファイルは/usr/share/nginx/html/foo/bar.htmlであって、/usr/share/nginx/html/bar.htmlではない

そのような単純なマッピングを行いたい場合はrootではなくaliasを使う。

ACME challengeはhttp://domain.tld/.well-known/acme-challenge/randomnumberに対して行われるため、 rootで正しい。

だが、このディレクトリがないので作っておいたほうが良いようだった。

% sudo mkdir -p /var/lib/letsencrypt/.well-known/acme-challenge

あとはcertbotを使えば良いのだが…

% sudo certbot certonly --email webmaster@domain.tld --webroot --webroot-path /var/lib/letsencrypt/ -d domain.tld

その前にConoHaのサーバー設定でHTTPをあけておかなくてはならない。 そして、IPv4とIPv6両方をあけておくこと。 別々になっていることに気づかず、ACME Challengeのリクエストが到達せずに(/var/log/nginx/access.logを見ても記録されていない)随分とハマってしまった。

移行作業

各ドメインごとのドキュメントルートを作り、ファイルを配置、 さらに対応したドメインごとの設定ファイルを作る。

今回の場合、Mimir Yokohamaのページは既にPureBuilder Simplyによる静的ファイルへのビルドが完了しているし、 移行対象のものに関してもPureBuilder2で静的ファイルにビルドされているものなので、単純にファイルを配置するだけの簡単なお仕事である。

Aki SIE関連のアドレスはdiscontinuedなので、301を返す。

server {
        listen 80;
        listen [::]:80;
        server_name aki-sie.com akisie.com aki-sie.yokohama akisie.yokohama;

        return 301 http://www.mimir.yokohama/;
}

http://journal.reasonset.net/に関しては301でリダイレクトしていたので、これも反映する

server {
        listen 80;
        listen [::]:80;
        server_name journal.reasonset.net;
        return 301 http://chienomi.reasonset.net$request_uri;
}

NginxのLet’s encryptの対応

メールサーバーの移行まで完了した時点で作業を行うのだが、 certbotで必要なドメインをすべて署名してもらったら、1SSL対応化を行う。

設定例は以下

server {
  listen 80;
  listen [::]:80;
  listen 443 ssl http2;
  listen [::]:433 ssl http2;

  ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/domain.tld/chain.pem;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:50m;
  ssl_session_tickets off;
  ssl_prefer_server_ciphers on;
  add_header Strict-Transport-Security max-age=15768000;
  ssl_stapling on;
  ssl_stapling_verify on;

  server_name domain.tld;

  index index.html;
  location / {
    root /var/www/domain.tld/doc;
  }

  # ACME challenge
  location ^~ /.well-known/acme-challenge {
    root /var/lib/letsencrypt;
  }
}

メールサーバーの移行

機能させるために一旦古い証明書で作業しているため、Let’s Encryptの証明書が取れたら証明書ファイルを変更してreload/restartすること。

Postfix

Postfixに関してはCentOS 6とArch Linuxではファイル配置が異なり、 バージョンの違いから設定ファイルの違いも大きく互換性に乏しい。

そこで、CnetOSの設定ファイルを/etc/postfix.centとしてコピーする。 このほか、/etc/alias*も忘れずに移行する必要がある。 また、一旦古い証明書ファイルもコピーした。

設定ファイルの違いを見るため、diffを取る。

% diff /etc/postfix.cent/main.cf /etc/postfix/main.cf > main.diff
% diff /etc/postfix.cent/master.cf /etc/postfix/master.cf > master.diff

このdiffファイルをkwriteで2開く。 今回はNemoのsftp機能を使って開いた。

このdiffを元に手作業で変更箇所を反映していく。 主にssl, auth, virtual関連の変更を反映する必要があった。

virtual関連のファイルは/home/mailuserにあったため、これをコピーする。 ただし、これはvirtualメールボックスを含むため、移行完了までは継続的にアップデートする必要がある。 この前にvirtual用に設定していたmailuserを設定する必要もあった。

% sudo useradd --no-create-home --uid=20000 --shell /bin/nologin --system -U -M mailuser

だが、これだけではグループが適正な値にならない。 そこで、グループIDを変更した上で、ユーザーの所属する主グループIDも変更する。

% sudo vigr
% sudo vipw

Postfixをrestartして完了。

Dovecot

Dovecotに関しては設定ファイルをコピーしてそのまま使うことができた。

Dovecotの設定ファイルとして/home/mailを使っていたので、これをコピーする。

Dovecotをrestartして完了。

上流

DNSを変更してもDNSキャッシュの関係でまだ旧サーバーにもメールが届く。 ある程度はaliasを使って転送しても良いのだが、素直にPostfixで受け取りつつ、Maildirのファイルを同期していくのが良いだろう。

DeleGateを使っていたため、DeleGateのSMTP転送機能を使う方法もあるのだが、うまく動作しなかったのと、TLS接続を受け付けることができないため、諦めた。

セキュリティ関連

複雑な話になるので省略。

そこまで難しいことをしているわけではないが、 普通の対策と、らしい対策とで簡単には突破できないようにしている。

後処理(旧サーバー)

DovecotとDeleGateは停止してしまう。

Postfixは5日程度稼働したら停止してしまっていいだろう。3

その後、バックアップ(主にログや設定など)をとったらサーバー破棄である。

おまけ: ConoHaについて

DNS

ConoHaのDNSは高速である上に非常に設定しやすい。

これまで使用していたお名前.comのもの、XDomainのものは非常に設定しづらかったので、 これだけでもConoHaにする価値はあるレベルだ。

料金

コンピューティングリソースはDTIとあまり変わらないが、料金は約倍になった。

ただし、ConoHaの柔軟性やメリットを考えればそう悪くない。 両方持つと少々負担は大きいが4、一気に完全移行したためDTIを解約でき5、許容すべきコストアップだろう。

速度

速い。

「コンピューティングリソースは大きく変わらない」といったが、速度は明らかにあがった。 特にネットワークの高速化とストレージの高速化の恩恵は大きく、Webの応答性は明確に向上した。

柔軟性

DTI VPSは色々と柔軟性が足りず、困った。 特に、OSのバージョンをあげようにもサーバーがひとつしかないので、できない。 ConoHaなら

  • インスタンスが立てられるのでサーバー仕様変更もできる
  • OSが選べる。さらにカスタムイメージのアップロードも可能
  • サーバーのアップグレードが簡単にできる(512MBプランを除く)

ファイアウォール

上流でフィルタリングしてくれるのはとても嬉しい。 設定が楽になる、というのもあるが、サーバーの耐障害性が勝手にあがる上に、まあまあ重いiptablesでの処理量が減るため、パフォーマンスが改善する。 リソースが限られている中では非常に嬉しい。


  1. Let’s Encryptの証明書はSAN(Subject Alternative Name)に 対応したもので、fullchain.pemが全てのドメインに対応したものになる

  2. Kwrite/Kateにはdiffのハイライト機能があるからだ

  3. TTLは3600だったため、それに従うならば1時間待てば良いのだが…

  4. DTIが月額500円ほど(年間6000円程度), ConoHaが900円ほど(年間10800円程度)である

  5. といっても、私はDTI SIMの契約があるため、DTIの契約そのものが終了するわけではない

サーバーを使ったConoHaを使うと幸せになれるnの理由

はじめに

この記事はConoHa Advent Calenderとして書かれたものである。

Qiitaのみなさん、ConoHa愛好家のみなさん、はじめまして。 コンニチハ、ハルカデス。

Qiitaをよく見ている人ならこのブログをご覧頂いたこともあるかもしれない。 技術的な記事を期待しているかもしれないが、今回はカテゴリからしてもおわかりの通り、ビジネス的なお話である。

ConoHaについて

ConoHaはGMOグループが提供しているVPSサービスである。 以前はVPSではなくレンタルサーバーを名乗っていたような気がするが、最近はVPSだと言っている。

「三雲このは」というマスコットキャラクターで有名なサービスになる。

そのためにサービス自体については軽視されがちなのだが、サービスも特徴的である。

ホスティングサービス, VPS

まず、かなり難しい区分なのだが、web基準で考えると次のような段階がある。

  • 用意されているアプリを使うだけ
  • 用意されているスペースにファイルが配置できる
  • サーバーを操作できる
  • サーバーを構築できる

アプリを使うだけ、というのはブログやECなどの特定の機能を持ったアプリケーションによるサイト公開が可能になっているものだ。 主立ってはamebloやSeeSaaなど、ConoHaと同じGMOグループではGMOペパボのJUGEMや、GMOメディアのYaplogなどがある。

さらに、GMOペパボには「ホームページ作成サービス」系のGoopeもある。 Qiitaもこの形態のひとつであるといえる。

用意されているスペースにファイルが配置できるのは、かつてのGeocitiesが有名で、 これを有料のサービスで行うというのはかつてはひとつの頂点であったとも言える。 最近は減ったがかつては多彩なサービスがあった。 GMOペパボのLolipopはその中でも有名にして定番のものだろう。私も以前は使用していた。また、同社はHetemlという上位サービスも用意している。 GMOインターネットもドメインサービスのお名前.comの一環として提供していたりする。

残る2者はいわゆるroot権限がとれるタイプのものだ。 前者はサーバーの再インストールや、サーバーのOS選択などは基本的にできない。後者はサーバーのインストールや追加なども可能なものだ。

VPS

VPSという語に明確な定義というか、区別はないようだ。 VPSという語が登場した当初のことを考えると、基本的に「rootがとれる従量課金のサーバー」という意味合いであったように思われる。 実際、VPSと名乗るもので、従来のホスティングサービスとの違いが「従量制課金である」ということ以外にあまり明瞭なものがなかったのである。

VPSで当初よりAmazon AWSは非常に強力なサービスであったが、 通信料など外部的要因によって変動する事象によって従量課金となるため、軽い気持ちでサーバーを立てた人が月に数十万円の請求をされる事案も少なくなかった。

そのために、金銭的にかなり余裕があるのでない限りVPSは選択肢にはならなかったのが実情だ。

ConoHaは当初その中間のような存在だったと言える。 VPSのようにいくつものサーバーを立てることができるが、料金はサーバー台数*プランというシンプルなもので、過大な請求がかかることなく安心して使用することができた。

現在のConoHa

当初と比べConoHaは幾分VPSらしくなった。 例えば計算資源からは独立したストレージ容量や、時間従量制などだ。

時間従量制というのは、携帯電話料金のような上限つき従量制と近いものだが、 例えば512MBプランは月額630円で、1時間あたり1.0円。24時間*31日だと744円であるため、それよりも安く収まることになる。

普通は従来型ホスティングサービスが月額制なのだから、現代では珍しい純粋なユーザーメリットによる料金体系である。

このために一時的な用途やテストサーバーなどを含め気軽かつ柔軟にサーバーを用意できることがConoHaの大きな特長である。

ライバル

このようなサービスはあまり類をみないように思うが、最大のライバルはやはりさくらインターネットによる「さくらのVPS」だろう。

このサービスも月額制で複数インスタンスが利用可能だ。 人気はこちらのほうが高く、周囲にも利用者が多い。

クーポンをイベントで配布していた、という点でも類似である。 ただし、ConoHaはクーポン配布はやめてしまったようだ。

お客様のサーバーにConoHaを

私が代表を務めるMimir Yokohamaでは、サーバーを使用するサービスを提供する際には指定がない限りConoHaを使用している。

これは、私がConoHaからコミュニティ支援を受けているという事情もあるが、 別にこれは他サービスの利用を制約するものではない。 ConoHaを使用しているのは、それによってエンジニアとお客様が幸せになるためだ。

サーバーを伴うサービスの展開戦略

自社で使用している巨大なインスタンスにすべて格納する「共有サーバー」スタイルを採用している事業者も多いだろう。

実際のところ、Mimir Yokohamaのお客様のご要望は、サーバー一台用意するのはコスト的に見合わないタイプ(アクセスの少ないウェブサイトなど)と、 共有させるのは難しいタイプ(XMPPサーバーを立てたり、アプリケーションサーバー必要とするケース)が混在している。

ひとつの仮想ホストですべてを賄おうとするのは、管理面を考えてもあまりうれしいことはない。 パフォーマンス低下によってお客様にもストレスをかけてしまうかもしれないし、 セキュリティ的に分離したいケースがあることも普通に考えられるのだ。

つまり、多少アップグレードしてでも複数の環境をホスティングする共有タイプのサーバーを提供してコストを抑えるべきケースと、 性能は控えめでもサーバーを専有すべきケースがある。

これをroot権限があるタイプのレンタルサーバーで行うのは、費用がかさむ上に管理も大変だ。 以前そのようなサービスを提供していたこともあるが(Mimir Yokohamaができるより前の話だ)、正直労力に見合わないものであった。

ConoHaならば仕様の異なる複数のインスタンスを立てることができる。 事業の拡大とともにインスタンスをどんどん増やしていっても構わないのだ。

2GBプランであれば共有webサーバーにも十分耐える。 上手に構成すれば1GBプランでも十分だ。 (分散できるのであれば1GBプランのホストを2つ用意するほうが負荷は厳しくない)

負荷の少ない環境で専有サーバーが必要なケースは512MBプランのインスタンスを使うといいだろう。

性能面

私は個人サイトはDTIのサーバーで運営しているのだが(このブログはまた違う)、速度的にはConoHaにとてもかなわない。 最大の理由は「すべてSSDで提供している」というストレージバックボーンだろう。 Mimir YokohamaのWebプランは可能な限り静的ページとして提供する構造をしている。 そのため、ほとんどストレージ性能と帯域で速度が決まる。「高速なウェブページ」を売りにする以上、インフラが遅いことによる限界というのは悲しいものがある。

もちろん、湯水のようにお金を使えば大幅なパフォーマンスアップも可能なのだが、 「リソースが足りてさえいればコストを抑えても性能が確保できる」というのは非常に嬉しいポイントだ。 仕方なくサーバーを使われるお客様というのは、なるべくなら費用は抑えたいとしつつも、性能はストレスのないものだと信じているものだ。 あまり性能が劣っているとお客様が悲しまれてしまう。

ConoHaは最小の512MBプランを、ちゃんと「多くのリソースは使わない」というだけの理由で選ぶことができるのだ。

以前はConoHaよりもさくらのVPSのほうが安かったのだが、現在は最小プランではほぼ同等の内容でConoHaのほうが少し安い。 1GBプランはConoHaのほうが安いにもかかわらず、SSDの容量はConoHaのほうが大きい。 Mimir Yokohamaは一般のお客様が中心であるため、これらのプランが中心となる。

この「費用の小さいプランでも満足度が高い」ということは、サービスを提供する際の価格設定を抑えられるということにもなる。 サーバー側の金額が安いとあまり大きな利益を載せにくいという面はあるが、安い価格から提供可能なサービスは競争力を向上させるだろう。

イメージ保存機能

サーバーを「凍結したい」という場合や、「移行したい」「サーバーは廃止するがデータは損失したくない」というケースは意外と多い。 サービスを開始する際にサービスを終了することを考えたくない気持ちはわかるのだが、 良いサービスのためには「お客様が気持ちよく完了できること」は不可欠な要素なのだ。

イメージ保存機能はこうしたケースにおいて極めて便利だ。 イメージ保存機能の存在によってお客様に柔軟な終了戦略を提示することができる。

API

ConoHaにはAPIがある。 これはさくらのVPSに対するアドバンテージでもある。

APIを使用することでサーバーの管理を容易にすることができる。

多くのサーバーを展開する場合において手作業の量を減らせば価格設定も抑えることができ、 それは事業の強みとしても活かせるはずだ。

しかも、APIはシンプルなJSONであるため、書くのも簡単。 このような機能をスマートに活用することは、優れたサービスとして欠かせない作法であろう。

カスタムISOからのインストール

重要なのはISOイメージによるインストールが可能なことだ。

Mondo RescueによってシステムバックアップのISOイメージ化か可能であるため、ローカルな仮想環境で練った(アップデートも済ませた)サーバーイメージをテンプレートとして使用することで、スタートアップの時間と労力を減らすことができる。

これは納期を急がれるお客様のご要望にお応えできることに加えて、 コストの大幅な削減にもつながる。

無駄な手間をかけることで価格を釣り上げるような戦略はとるべきではない。 お客様が本当に必要とされているもののためにより多くの労力をかけるべきなのだ。

これは、VPSでなければ難しい(場合によってはVPSですらも難しい)Arch Linuxによるサーバーによって 少ないリソースでもパフォーマンスを発揮するという点でも活用されている。

海外リージョン

今は日本でも海外の顧客を相手にする企業は大変多い。

B2Bサービスを提供する場合、お客様は海外向けにサービスを提供される場合は多いのだ。 実のところ海外とのトランジットが割と少ない日本のサーバーというのは、海外から見るとあまりうれしくない。 どこかの果てにある得体のしれないサーバーであり、実際に応答が遅い。 これは我々が日本からベルギーやデンマークあたりのサーバーにアクセスすれば体験できる事象だ。

私もお客様が海外と商売をされているケースというのは「意外なほど多い」という印象を受けている。 このようなケースにおいてはやはりサーバーも日本ではなく適切な場所に配置したいところだ。

ConoHaにはアメリカとシンガポールという、「適切な場所」としやすい2箇所が用意されている。

このおかげでよりお客様にとってかゆいところに手が届くサービスを展開しやすくなっている。

提灯記事?いやいや…

なんといってもこの記事はConoHaのAdvent Calenderのために書いたものだし、 私がコミュニティ支援を受けているということもあり、PR記事疑惑は拭えないところだろう。

だが、そんなことはない。 なんといっても、特にこの記事作成にあたってConoHaから見返りを得ていないのだ!!!!! (もちろん、見返りをいただけるのなら大歓迎である!!!!!)

実際にMimir Yokohamaのサービスというのは、「ConoHaがある」ということが先にあった。 つまり、Mimir Yokohamaにラインナップされているサーバーを利用するタイプのサービスは、 いずれも私が「ConoHaがあるからこんなこともできる」という発想によって設定したものであり、 ConoHaがなければこれらのサービスは存在しなかった可能性が高い。 実際、ConoHaとの関係がなかった初期にはサーバーを使うサービスというものは非常に限定的であった。

もちろん、ConoHaがなくてさくらのVPSがあるという状況であれば、 いずれそのようなサービスを考えてさくらのVPSを使って展開していた可能性は高いが、 ConoHaを使うことによってお客様にメリットを提供しつつ、 それを事業の強みとして活用することができているのだ。

それどころか、一時期「ConoHaを活用できる」ということは、事業の価値において非常に大きな割合を占めていた。 そのようなVPSの利用があまり一般的でなく、圧倒的に低価格に、かつ柔軟にサービスを構成することが可能だったからだ。

Mimir Yokohamaはお客様の笑顔のために、ConoHaを利用しています。

新品コンピュータを初期状態に戻せるようにバックアップ

これは何

新品コンピュータを購入したときに、完全に元の状態に復元できるようにするものである。

バックアップ手段は色々とあるのだが、もっとも確実かつ完全な手段が「ディスクの完全なクローンを得る」という方法だ。

その方法について紹介しよう。

なお、これは「やや複雑な手段をとっても効率的に、確実に元に戻せる手段を構築したい」という人向けであり、 そのような場合は諦めるという人や、考えたり努力することを回避したいという人は対象としていない。

新品ならでは

新品のコンピュータのディスクは、ファイルをコピーしているわけではない。 データを流し込んで複製しているのだ。

一般的には、先頭からWindowsシステム用の領域が書き込まれ、そして末尾にバックアップ用の領域があるのが一般的である。 バックアップ用の領域はパーティションが切られ、その中に格納されていることもあるし、パーティションレイアウトの末尾の後ろに配置される場合もある。

このため、データが書かれているのは先頭と末尾のみで、中間は全くデータがなく、0が書かれている。

128GBのディスクをフルクローンした場合は当然ながら128GBのファイルが出来上がる。 だがしかし、連続する0のデータは圧縮すると極めて小さくなる。そのため、このようなディスクイメージは圧縮することによって非常にコンパクトにできるのだ。

これが使用していたディスクであればうまくいかない。 データが記録されていない領域も0で埋められているわけではなく、ごちゃごちゃに記録された状態になっているため、フルディスクイメージを圧縮したときに極端に小さくなることはない。 そのため、完全性や確実性が低下してでもなるべくコンパクトな形式でバックアップするのが一般的なアプローチになる。(partimageやntfscloneなどを使うということだ)

書き戻しに関して

次のようにして取得したイメージは

$ dd if=/dev/sda | xz -z -c > /mnt/sda.img.xz

次のようにして書き戻すことができるのだが

$ xz -d -c /mnt/sda.img.xz > /dev/sda

この場合、128GBの「元のディスクに」書き戻すことを前提している。

サイズが違う場合どうなるかというと、ディスクが大きければパーティションがディスク全域ではなく途中で終了し、途中にリカバリー用の領域が置かれた状態になる。 ディスクが小さい場合はパーティションがディスクのサイズよりも大きく設定されてしまう。 この修正はちょっと大変だ(Windows上では難しいかもしれない)。

だが、実際のところリカバリー領域は書き戻しによって復元できているため、なくなってしまっても構わない、と考えられる。 そして、パーティションテーブルはパーティションの内容より前にある。 よって「先頭からデータのある分だけを復元すれば良い」ということになる。

このため、復元したデータは全部書く必要はなく

$ xz -d -c /mnt/sda.img.xz | dd of=/dev/sda bs=1024M count=10

のようにすれば良い(1024MB=1GiBを10回なので10GiB書き込むことになる)。 内容としてはどのみち残りは0なのであり、書いてもかかなくても同じだ。 ディスクサイズが異なる場合はパーティションサイズのみ変更すれば良い。

バックアップの仕方

Linuxで起動する…ところまでは省略しよう。 UnetBootinなどの使用は勧めないが。

まずはpartedでディスクを確認しよう

$ sudo parted -l

これによって各ディスク名(/dev/sdaなど)を得ることができる。 ここではバックアップ対象のディスクはsdaであるとしよう。 異なる場合は読み替えること。

リムーバブルディスクにバックアップ

モダンなLinuxシステムではリムーバブルディスクを接続すれば認識され、ファイルマネージャが起動する。

ファイルマネージャ上でリムーバブルディスクを開き、そこで右クリックから端末(ターミナル)を開く、とする。 そして

$ dd if=/dev/sda bs=64M of=recover.img

のようにする。 もし、圧縮も同時に行うのであれば

$ dd if=/dev/sda bs=64M | xz -z -d > recover.img.xz

のようにする。時間がかかっても圧縮率を上げるのであれば

$ dd if=/dev/sda bs=64M | xz -z -d -e -9 > recover.img.xz

とすれば良い。

なお、NASなどのネットワークドライブ上に保存する場合も似た手順で行うことができる。

ネットワーク上のLinuxホストに対して行う

もう、説明がいるのかどうかも怪しいが、計算機母艦となるLinuxを運用している場合は 受け取る側のLinuxホストではnetcatをインストールしておく。

そしてnetcatで通信を待機する。 次の例ではBSD netcatを使用する。

$ nc -N -l 22500 > recover.img

受け取り側で圧縮する場合は次のようにする。

$ nc -N -l 22500 | xz -z -d -e -9 > recover.img.xz

送り側はncなどはない場合が多いだろうし、ライブブートではインストールも難しい。 しかし、bashにはTCP機能があるため、これを利用する。

$ dd if=/dev/sda bs=64M > /dev/tcp/192.168.1.128/22500

注意点は、bashでなければならないこと、そしてファイルに書けばよいわけではなくリダイレクト機能を使わなければいけないことだ。