dorapon2000’s diary

忘備録的な。セキュリティとかネットワークすきです。

mediatombでDLNAサーバを構築

ubuntuサーバを立て出したのは、立ち読みしておもしろそうで、そのまま購入した日経Linuxのせいです。

日経Linux(リナックス) 2016年 10月号 [雑誌]

日経Linux(リナックス) 2016年 10月号 [雑誌]

一通りサーバの設定も終わったところで、 「07 MediaTombでDLNAサーバーを構築」をやってみました。DLNAサーバというのは家電、ゲーム機、スマフォで動画や音楽を共有するためのサーバらしいです。MediaTombがそのためのサーバーソフトです。本の説明では非常に簡潔に書かれているのですが、全く一筋縄にはいかず、最後の最後で諦めました。一応たくさんの資料を読んだのでまとめておいて、もし誰かの参考にでもなればと思います。


前提

流れ

  1. mediatombのインストール
  2. mediatombの設定
  3. mysqlの設定
  4. ブラウザで共有するファイルを選択
  5. DLNAクライアントで動画を確認

mediatombのインストール

$ sudo apt-get install mediatomb

mediatombの設定

設定ファイルは2つあります。

  • /etc/default/mediatomb
  • /etc/mediatomb/config.xml

手作業でも設定できますが、本ではコマンドですべて設定してしまっています。 私もそれに従いました。

# 共有設定用のweb画面(管理画面)にアクセス可能にする
$ sudo sed -i -e ’s/enabled=“no”/enabled=“yes”’ /etc/mediatomb/config.xml

# ネットワークデバイス名を確認
$ ip link
...
2: wlp3s0b1: <BROADCAST, ...

# 外部からアクセス可能にする (2つ目のINTERFACE=の部分は先程のデバイス名を入れる)
$ sudo sed -i -e ’s/INTERFACE=“lo”/INTERFACE=“wlp3s0b1”' /etc/default/mediatomb

# システム起動時の自動起動を設定 (本ではsystemctlを使用)
$ sudo sysv-rc-conf mediatomb on

# ユニバーサルプラグアンドプレイライブラリを更新
$ wget http://bugs.launchpad.net/ubuntu/+source/libupnp/+bug/1571199/+attachment/4638260/+files/libupnp6_1.6.19+git20160116-1_amd64.deb
$ sudo dpkg -i libupnp6_1.6.19+git20160116-1_amd64.deb

# 再起動
$ sudo reboot

本ではこれでhttp://localhost:50500/にアクセスすれば管理画面が開くとなっていますが、なりませんでした。

$ sudo cat /var/log/mediatomb | tail
…
ERROR: You enabled both, sqlite3 and mysql but only one database driver may be active at a time!

起動時に失敗しているらしくログを見てみると、sqlitemysqlが両方onになっているから片方にしろということでした。

$ sudo vi /etc/mediatomb/config.xml
…
-<sqlite3 enabled=“yes">
+<sqlite3 enabled=“no">
...

sqlite3だけnoにしてmysqlを有効にしました。 しかし再びエラー。

$ sudo cat /var/log/mediatomb | tail
…
ERROR: error in configuration, transcoding profile "oggflac2raw" could not find transcoding command ogg123 in $PATH

次はogg123というコマンドがないということなので、vorbis-toolsをinstallします。

$ sudo apt-get install vorbis-tools

三度目のエラー

ERROR: error in configuration, transcoding profile "vlcmpeg" could not find transcoding command vlc in $PATH

似た感じですが、結構悩まされました。結論から言えばvlcは例のVLCのことで、それをinstallするだけで済みます。

$ sudo apt-get install vlc

mysqlの設定

mediatombについて調べていると、mysqlの設定はしなくてもうまくいくっぽいのですが、私のところでは四度目となるエラーがログに記されてました。

ERROR: The connection to the MySQL database has failed: mysql_error (1045): "Access denied for user 'mediatomb'@'localhost' (using password: NO)"

仕方ないので、mysqlにmediatombというユーザを作ってmediatombというデータベースを割り当てます。

$ mysql -u root -p
mysql > create database mediatomb;
mysql > create user ‘mediatomb’@‘localhost' identified by ‘media tomb’;
mysql > grant all privileges on mediatomb.* to ‘mediatomb’@‘localhost’;
mysql > flush privileges;
mysql > exit;

# データベースの雛形作成
$ mysql -u mediatomb -p mediatomb < /usr/share/mediatomb/mysql.sql

デフォルトではmysqlのパスワードはないもので設定されているので、パスワードをconfig.xmlに追加しておきます。

$ sudo vi /etc/mediatomb/config.xml
...
<mysql enables=“yes”>
  <host>localhost</host>
  <username>mediatomb</username>
 +<password>mediatomb</password>
  <database>mediatomb</mediatomb>
</mysql>

ここまでやって、やっとエラーは出なくなります。

ブラウザで共有するファイルを選択

http://[server-ipaddr]:50500/にアクセスできます。

ログイン画面はconfig.xmlで指定したユーザー名とパスワードでログインできます (デフォルトはmediatomb:mediatomb)。

左上に [ Database | Filesystem] とあるので、Filesystemを選ぶとサーバの中身が木構造になって表示されます。音声ファイルや動画ファイルのところまで辿り、右の+ボタンを押すと共有されます。共有されたファイルやディレクトリはDatabaseで確認できます。私はなぜか画面を更新しないと確認できませんでしたが。

こちらのサイトで詳しく説明されていました。 How to Add Content to MediaTomb

以上でサーバ側の設定は完了です。

補足

config.xmlにmimetypeを追加

<extension-mimetype ignore-unknown="no”>
...
 +<map from="mp4" to="video/mp4"/>
</extension-mimetype>

config.xmlで日本語設定

<import hidden-files=“no”>
 +<filesystem-charset>UTF-8</filesystem-charset>
 +<metadata-charset>CP932</metadata-charset>
 +<playlist-charset>UTF-8</playlist-charset>

私はこの設定をしても文字化けが直りませんでした。

ubuntuにおけるvlcmpeg

公式サイトによると、vlcmpegはデフォルトだと動かないらしいです。参考にしていたどの日本語のサイトにもなってなかった話でよくわかりません。

<agent command=“vlc”...
-vcodec=mp2v
+vcodec=mp1v 

DLNAクライアントで動画を確認

macで見られるDLNAクライアントには、なんとVLCがありました。

と喜ぶのもつかの間、VLCのローカルネットワーク - ユニバーサルプラグ & プレイに共有ファイルが表示されるはずが、なにも表示されません。サーバのIPアドレスなどを設定しなくていいのかと疑問に思うも、VLC 2.* は、なにもしなくても表示されるようです。ただ、一部で表示されないような不具合もあるようで*1、もしかしたらこれにあたるのかもしれません。サーバ上のログは何もエラーを吐いていませんでした。


VLCは諦めてこちらも無料のKODIと呼ばれるソフトをダウンロードしました。かなり豪華なUIに驚きます。

さっそくDLNAサーバに繋いでみると、ちゃんと登録した共有ファイルの一覧が見れます。見たい動画をプレイリストに登録して、いざ視聴。が、残念ながらここで終わりです。視聴できませんでした。サーバ側はまったくエラーを吐いていません。 mac側のログを見てみると次のようになっていました。

$ cat ~/Library/Logs/kodi.log| tail -n 30
...
07:12:35 T:140735217373952  NOTICE: DVDPlayer: Opening: http://192.168.150.50:50500/content/media/object_id/3619/res_id/0/ext/file.mp4
07:12:35 T:140735217373952 WARNING: CDVDMessageQueue(player)::Put MSGQ_NOT_INITIALIZED
07:12:35 T:4704055296  NOTICE: Creating InputStream
07:12:35 T:4704055296   ERROR: CCurlFile::Stat - Failed: Couldn't connect to server(7) for http://192.168.150.50:50500/content/media/object_id/3619/res_id/0/ext/file.mp4
07:12:35 T:4704055296   ERROR: CCurlFile::FillBuffer - Failed: Couldn't connect to server(7)
07:12:35 T:4704055296   ERROR: CCurlFile::Open failed with code 0 for http://192.168.150.50:50500/content/media/object_id/3619/res_id/0/ext/file.mp4
07:12:35 T:4704055296   ERROR: Open - failed to open source <http://192.168.150.50:50500/content/media/object_id/3619/res_id/0/ext/file.mp4>
07:12:35 T:4704055296   ERROR: CDVDPlayer::OpenInputStream - error opening [http://192.168.150.50:50500/content/media/object_id/3619/res_id/0/ext/file.mp4]
07:12:35 T:4704055296  NOTICE: CDVDPlayer::OnExit()
07:12:35 T:140735217373952   ERROR: Playlist Player: skipping unplayable item: 0, path [upnp://e0c9f427-1f7a-42b5-9bcd-077b774c87fd/3619/]
07:12:35 T:140735217373952  NOTICE: CDVDPlayer::CloseFile()
07:12:35 T:140735217373952  NOTICE: DVDPlayer: waiting for threads to exit
07:12:35 T:140735217373952  NOTICE: DVDPlayer: finished waiting
07:12:35 T:140735217373952  NOTICE: CDVDPlayer::CloseFile()
07:12:35 T:140735217373952  NOTICE: DVDPlayer: waiting for threads to exit
07:12:35 T:140735217373952  NOTICE: DVDPlayer: finished waiting

Failed: Couldn't connect to server(7)
ここが一番の原因っぽいのですが、調べても私と状況が違うものばかりでてきて、結局力尽きました。(vcodec=mp1vの場合、mp2vとするとまた別のエラーが出ます)

余力があれば、いつか使えるようにしたいですね。

参考

mysql関連

vlc関連

kodi関連

ubuntu server 16.04LTS をWifiにつなげる

知識不足でWifiにつなげるだけで非情に苦労しました。


前提

linuxでのwifiへの接続方法

2種類あるようです。

  • iwconfig
  • wpa_supplicant

一般的にはwpa_supplicantのようですが、WEPのときはiwconfigでも設定できるようです*1。 WPAやWPA2のときはwpa_supplicantが必要です。 私のルーターはWPA2-PSK-CCMPなのでwpa_supplicantを使いました。

流れ

  1. wpa_supplicantのinstall
  2. wpa_supplicant.confを作って、wifiの接続方法などを設定する
  3. /etc/network/interfacesをいじって起動時にWifiへ接続するようにする
  4. 謎のエラーと戦う

wpa_supplicantのinstall

$ sudo apt-get install wpa_supplicant

私の環境では、はじめから入ってました。

wpa_supplicant.conf

wpa_supplicant.confは接続するSSIDや接続方式、パスワードを記述する設定ファイルです。 まず、wpa_passphraseコマンドを使って雛形的なものを作ります。

$ wpa_passphrase my_ssid my_passwod
network={
    ssid="my_ssid"
    #psk="my_password"
    psk=e53bb7df43156b8a6ad5d3ea5bb4078fada2531e2d5d5208c3bc1a17c3278220
}

これだけではターミナルに表示されるだけなので、ファイルに出力します。

$ sudo wpa_passphrase my_ssid my_passwod >> /etc/wpa_supplicant/wpa_supplicant.conf

wpa_supplicant.confを書き換えて次のようにします。

ctrl_interface=/var/run/wpa_supplicant # UNIXドメインソケットを作成する領域
ctrl_interface_group=wheel # 上記UNIXドメインソケットの所有グループ

network={
    ssid="my_ssid"
    #psk="my_password"
    psk=e53bb7df43156b8a6ad5d3ea5bb4078fada2531e2d5d5208c3bc1a17c3278220
    key_mgmt=WPA-PSK # 暗号化キーの管理方式
    proto=RSN # 認証方式
    pairwise=CCMP # ユニキャスト用暗号化方式
    group=CCMP # ブロードキャスト/マルチキャスト用の暗号化方式
}

重要なのはnetwork={}に追加した4項目です。

  • key_mgmt は WPA-PSK でも WPA2-PSK でも WPA-PSK が入る。
  • proto は WPA-PSK なら WPA、WPA2-PSK なら RSN
  • parwise と group は恐らく同じものが入る。TKIP または、CCMP (AESのこと)。

ここらへんは以下のサイトが理解の助けになりました。 security.nekotricolor.com

なお、修正すればWEPも設定できます。詳しくは Linuxで無線LAN (ゆうちくりんの忘却禄) で少し紹介されています。

実行する

wpa_supplicantコマンドはオプション(-i -c)と値をくっつけることに注意です。

$ sudo wpa_supplicant -iwlp3s0b1 -c/etc/wpa_supplicant/wpa_supplicant.conf 
...
CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:xx:xx completed ・・・

このようなメッセージが出れば成功です。Ctrl-Cで停止して改めてバックグラウンドで実行します。

$ sudo wpa_supplicant -iwlp3s0b1 -c/etc/wpa_supplicant/wpa_supplicant.conf -B

少し話がそれますが、wlp3s0b1というのはwlanのことです。 新しい命名規則によって、wlanではなくそのようにつけられてそうです。 調べながら知りましたが、詳しくはこちらに。 qiita.com

ちなみに、以下のように、wlan0からrenameされていることがわかります。

$ dmesg | grep wlp3s0b1
[   18.439600] brcmsmac bcma0:1 wlp3s0b1: renamed from wlan0

起動時にWifiへ接続するようにする

先程のやり方では再起動するたびにコマンドを打ち込まなくてはいけないので、起動時に設定するようにします。

$ sudo vi /etc/network/interfaces
--- 

auto lo
 
iface lo inet loopback
 
auto wlp3s0b1
allow-hotplug wlp3s0b1
iface wlp3s0b1 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

ここでは起動時にdhcpサーバ (ルーター) にIPアドレスを割り当ててもらうようにしています。 細かい書式はこちらで詳しく説明されています。自分自身いまいちわかっていませんが。 qiita.com

謎のエラーと戦う

実際は次のようなメッセージ(エラー?)が出て、とても悩まされました。 (dmesg中の一部が突然がターミナルに出力される)

cfg80211 invalid regulatory domain detected

しかし、wifiはつながっているのです。

答えはInvalid JP regulatory domainで見つけました。 どうやら、指定された範囲内に周波数が少し収まっていないぞということらしいです。 そこで友人に借りていたOpenWrt内蔵のBuffalo WZR-HP-AG300Hをルーターとして使っていることを思い出しました。 OpenWrtはカスタマイズ性に優れすぎたファームウェアです。 ちゃんと設定してないと確かにそういうこともあるかもと確認をしていると、さればよ。 ロケール設定がデフォルトの「00 - 世界」のままでした。 国によって使える周波数帯が異なるのだから、ここを設定しなくては範囲が合わないということです。

ということで「JP - Japan」に変えたら、メッセージは出なくなりました。

追記

一度成功したからブログを書いたんですが、再起動したらwifiに繋がらなくなってしまいました。 原因は今のところ2つありました。

  • ubuntuにはwheelグループがない
  • dhcpクライアントがうまく起動してない

wheelグループがないのは知りませんでした。いずれ必要になると思い、以下のサイトを参考にwheel作りました。 kawairi.jp
dhcpがうまく起動しないのはよくわかりません。今のところ手動でなんとかしてます。

$ sudo dhclient wlp3s0b1

参考

Microsoft Bot Frameworkを使ってSkypeボットを作る

Microsoft Bot Frameworkというものが4月から使えるようになっていたらしく、今まで作れなかったSkypeボットもそれで動かせるということで試してみました。ボットはheroku上で動かします。数ヶ月の間にちょくちょく仕様が変わっているようで、よく惑わされました。


公式リンク

必要なもの

  • Microsoftのアカウント
  • herokuのアカウント
  • Node.js

流れ

  1. Bot Builder for Node.js でボットを作る
  2. herokuにデプロイ
  3. Developer Portalでボットとして登録
  4. 登録する過程で得たappIdとappPasswordを環境変数に追加 (or ボットに直書き)
  5. スカイプチャンネルに対応させる

Bot Builderでボットを作る

$ mkdir mybot
$ cd mybot
$ npm init
$ npm install --save botbuilder
$ npm install --save restify

サンプルコードを参考にして、hello worldとだけ返すbot

// app.js

var restify = require('restify');
var builder = require('botbuilder');

//=========================================================
// Bot Setup
//=========================================================

// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
   console.log('%s listening to %s', server.name, server.url); 
});
  
// Create chat bot
var connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD
});
var bot = new builder.UniversalBot(connector);
server.post('/api/messages', connector.listen());

//=========================================================
// Bots Dialogs
//=========================================================

bot.dialog('/', function (session) {
   session.send('Hello World'); 
});

ボットの機能を左右させる部分はBots Dialogs以下の部分です。Bot SetupではappIdとappPasswordを環境変数から受け取る形式にしているので、appIdとappPasswordがわかり次第、環境変数を設定していきます (まだわからない)。環境変数から受け取らず、直書きしてももちろん大丈夫です。

参考にしたサイトではUniversalBotではなくBotConnectorBotが用いられていたのですが、現在は非推奨のようです。

herokuにデプロイ

$ git init
$ heroku create mybot
$ echo 'node_modules' > .gitignore
$ echo 'web node app.js' > Procfile
$ git add .
$ git commit -m "First commit"
$ git push heroku master

herokuの管理画面でHeroku Domainを確認する (恐らく、mybot.herokuapp.comとなっている)。

Developer Portalでボットとして登録

Register a botでボットを登録します。

  • Bot handle : 一意なボットのID (後の変更不可)
  • Messaging endpoint : http://[Heroku Domain]/api/messages
  • Microsoft App ID : 下のボタンで新しく作る (AdBlockを停止しないと反応しませんでした)。その際パスワードもメモっておく。
  • Privacy statement : http://[Heroku Domain]/privacy (今回は適当)
  • Terms of Use : http://[Heroku Domain]/terms (今回は適当)

appIdとappPasswordを環境変数に追加

先ほどの環境変数を登録します。 ローカルでは

$ export MICROSOFT_APP_ID=[appId]
$ export MICROSOFT_APP_PASSWORD=[appPassword]

heroku上でも環境変数として登録する

$ heroku config:set MICROSOFT_APP_ID="[appId]"
$ heroku config:set MICROSOFT_APP_PASSWORD="[appPassword]"

Skypeチャンネルに対応させる

Developer PortalMy botsの左下でherokuとちゃんとつながっているかTestできます。うまく行くとAcceptedと表示され、エラーなら表示してくれます。参考にしたサイトでは入力のテストもできるようなUIになってましたが、私の時はTestというボタンひとつだけでした。

そして、Skypeチャンネルをaddします。Skypeの[Add to Skype]を押して指示に従うと、ボットとSkype上で会話できるようになります。試しに何かメッセージを送ればHello Worldと返してくれるはずです。

https://join.skype.com/bot/[appID]のリンクで他の人にも紹介できます。ただし公式ドキュメントのQ&Aでは、私的利用や企業内での利用は考慮されていないとあります。調べてみましたが、publishしてない状態でグループにボットを入れることはできなさそうです。

参考

emacs上とシェル上でのバイトコンパイルの結果が違う

前の記事で気づいたバイコンパイル時のエラーについて、同じように困ってる人の助けになればと思い残しておきます。


前提

  • mac OSX Yosemite 10.10.5
  • emacs 24.5
  • init-loader
  • packagesでパッケージ管理

フォルダ構成は前の記事で書きました。

発生したエラー

$ emacs -batch -f batch-byte-compile inits/*.el

In toplevel form:
inits/00-basic.el:22:7:Warning: assignment to free variable `show-paren-style'
inits/00-basic.el:64:7:Warning: assignment to free variable `c-default-style'
inits/00-basic.el:82:1:Warning: cl package required at runtime
Wrote /Users/dorapon2000/.emacs.d/inits/00-basic.elc

In end of data:
inits/10-anzu.el:8:1:Warning: the function `global-anzu-mode' is not known to be defined.
Wrote /Users/dorapon2000/.emacs.d/inits/10-anzu.elc

In toplevel form:
inits/10-auto-async-byte-compile.el:5:1:Error: Cannot open load file: No such file or directory, auto-async-byte-compile
Wrote /Users/dorapon2000/.emacs.d/inits/10-color-theme.elc
Wrote /Users/dorapon2000/.emacs.d/inits/10-elscreen-persist.elc

...

いつものようにinits以下の.elファイルをすべてバイコンパイルしようとすると、全体的に上記の様な警告とエラーが出ました。 種類としては3つ。

  1. Warning: assignment to free variable `show-paren-style'
  2. Warning: the function `global-anzu-mode' is not known to be defined.
  3. Error: Cannot open load file: No such file or directory, auto-async-byte-compile

特に3.が出るとそのファイルがコンパイルされないのでなんとかしたかったです。 1.は調べるとあまり気にしなくていい感じでした。 2.は3.と原因が同じという雰囲気をしてます。

2.と3.について同じように悩んでる人はいないものかと検索しても、原因はヒットしませんでした。 同じような環境の人はたくさんいるはずなのに、なぜ自分だけこの問題が発生するのか未だにわかりません。

解決法

初心に戻ってバイコンパイルについて調べていて、 Emacsで設定ファイルを初めてバイトコンパイルする方法とその後自動で更新する方法 にある方法でバイコンパイルしたら、警告もほぼ出ずにするっとコンパイルできました。 しかし、それを.elファイルに書いてシェル上で実行してみてもうまくいきませんでした。

# 全部は長いので10-auto-async-byte-compile.elだけをコンパイルさせる。残りはコンパイルをskip。

$ cat byte-compile.el
(byte-recompile-directory (expand-file-name "~/.emacs.d/inits") 0)

$ emacs --script byte-compile.el
Checking /Users/dorapon2000/.emacs.d/inits...
Compiling /Users/dorapon2000/.emacs.d/inits/10-auto-async-byte-compile.el...

In toplevel form:
10-auto-async-byte-compile.el:5:1:Error: Cannot open load file: No such file or directory, auto-async-byte-compile
Done (Total of 0 files compiled, 1 failed, 36 skipped)

ここで思い当たるのはload-pathです。 ロードパスの通った(設定が一度読み込まれた)emacs上だからうまくいき、シェル上ではロードパスが読み込めておらず2.や3.のエラーがでる。 そこで、$ emacs -qで設定ファイルを読み込まずに起動して、先ほどの方法でコンパイルすると案の定できませんでした。 次に、(package-initialize)(ロードパスを読み込む)を実行してから試すとコンパイルできました。

最終的には以下のようにすることで、シェル上からでも正常にバイコンパイルできるようになりました。 (2.と3.が解決できました)

$ cat byte-compile.el
(package-initialize)
(add-to-list 'load-path "~/.emacs.d/elisp/auto-complete")
(byte-recompile-directory (expand-file-name "~/.emacs.d/inits") 0)

$ emacs --script byte-compile.el
Checking /Users/dorapon2000/.emacs.d/inits...
Compiling /Users/dorapon2000/.emacs.d/inits/10-auto-async-byte-compile.el...
Wrote /Users/dorapon2000/.emacs.d/inits/10-auto-async-byte-compile.elc
Done (Total of 1 file compiled, 0 failed, 36 skipped)

(add-to-list 'load-path "~/.emacs.d/elisp/auto-complete")について。 auto-completeはpackagesで入れたパッケージではなく、野良lispのため、別にload-pathを通す必要があるようでした。 しかし自分自身よくわかっておらず、packagesにもあるパッケージだからとそちらで改めて落としたのに、この行がないとコンパイルできませんでした。 そもそも、(package-initialize)でelisp/auto-completeのパスは通っているはずなのに、やはり書かないといけませんでした。

なぜ自分だけこの問題が起きたのか。なぜ以前はできていたものが今はできないのか。エラーが出るものと出ないものの差はなんだったのか。 疑問は山積みですが、なにはともあれシェル上からコンパイルできるようになって満足とします。