• symphonic-mpd特殊ネタ集

    @パパリウス さま
    あ、ここ見たことあります。deprecatedと書かれているためそのままは使えないなぁと諦めました。
    今度pcでvlcを起動させてchromecastに向かって音声ストリームを再生してみようと思います(個人所有のは初代のため、失敗するかも)。
    これがうまくいけばwiresharkでパケットキャプチャー出来れば色々わかるかも知れません。
    一応googleのオープンソース公開コードはダウンロード済ですが、2GBもあるため、まだ見ていません。

  • symphonic-mpdへのSD書込を減らす(その1)

    symphonic-mpdでは元々raspbianというディストリビューションを使用しており、
    これの元となる物はPC向けのdebianとなります。
    debian自体はaptというパッケージ管理ソフトを利用することで最新のソフトウェアに容易に更新できる大変便利な代物ですが、Raspberry Piという組込用途に近いワンボードPCである以上、ブートデバイスのSDカードの書込はできるだけ減らしたほうが良いでしょう。
    幸いsymphonic-mpdではパパリウスさまが調整した設定によりSDカードの書込頻度はかなり落ちていますが、ここでは更なる書込を減らす方向性について複数回に分けて説明します。
    (同時に皆さん一緒になって方向性を考えていきたい事項もありますので提案も兼ねたいと思います)。

    • 既に実施済みのOS書込の省略化
       近代的なOSではメインメモリの不足に備えて外部記録領域にスワップを用意します。raspbianも標準ではスワップの設定がonになっていますが、symphonic-mpdでは予めオフになっています。
       また、ログを書込領域についても既にtmpfsを採用し、メインメモリに作成したディスク領域に保存されます(そのため、現況ではリブート後に過去のログは消去されます)
      ↑これはそのうち再起動時前にバックアップするスクリプトを紹介予定。

    • 今回ご紹介するネタ(一時保存領域もメインメモリに確保)
       正直ネタとしては効果が薄い(ファイルの一時保存領域を真面目に使うプログラムがどのくらいあるのか不明なことと、これを行う上でのリスクを天秤にかけた場合)ですが、紹介します。
       やることとしては/tmpと/var/tmpの両方のディレクトリをtmpfsでメインメモリ上に移動してしまうということです。
      ※警告:今回のネタは最悪の場合、ディスクイメージからの起動ができなくなる恐れがあります。各コマンドの意味のある程度の事前理解と、自己責任で試行頂ますようお願いします。

    ①/etc/fstabの書替
     書替は# NAS Settingの手前に2行を追加する形になります。下記に書替済みのfstabを貼り付けします。

    proc            /proc           proc    defaults          0       0
    PARTUUID=55575038-01  /boot           vfat    defaults          0       2
    PARTUUID=55575038-02  /               ext4    defaults,noatime,nobarrier  0       1
    tmpfs           /var/log        tmpfs   defaults,size=32m,noatime,mode=0755      0       0
    tmpfs           /var/lib/mpd/music/RAM  tmpfs defaults,size=650m,noatime,mode=0777      0       0
    tmpfs           /tmp            tmpfs   defaults,size=32m,noatime,mode=0777      0       0
    tmpfs           /var/tmp        tmpfs   defaults,size=32m,noatime,mode=0777      0       0
    
    # NAS Setting
    //192.168.11.151/qmultimedia/Music/ /var/lib/mpd/music/NAS cifs ro,noauto,x-systemd.automount,sec=ntlmssp,vers=2.1,rsize=129940,cache=none,iocharset=utf8,username=********,password=********
    #//xxx.xxx.x.x/xxxxx/xxxxx /var/lib/mpd/music/NAS cifs ro,cache=none,noauto,x-systemd.automount,username=xxx,password=xxx
    

    今回追加した行の意味を簡単に説明すると以下の通りです。
    ・tmpfsというファイルシステムを使用して/tmpと/var/tmpをブート時に生成してマウントさせます。
    ・オプション設定のdefaults,noatimeはお呪いだと思っても結構です。size=32mはディレクトリの最大サイズを指定しています。
    ・mode=0777は生成されたディレクトリのパーミッションです(元々に合わせてあります)。
    ・更にデフォルトの設定を見ると/var/logと/var/lib/mpd/music/RAMはtmpfsでメインメモリに作られているのがお分かりでしょうか?

    ②SDカードのディレクトリを削除
    以下の通りコマンド入れます(先に/tmpを消した場合、/var/tmpを消そうとする間に/tmpが見つからない旨の警告が出て鬱陶しいです。)

    sudo rm -fr /var/tmp
    sudo rm -fr /tmp
    

    削除するディレクトリをくれぐれも間違えないようにして下さい。
    ③ラズパイのリブート+再起動
    以下の通りコマンドを入れます。いつもの起動音が鳴れば、恐らく成功です。

    sudo reboot
    

    念のため、sshでリモートシェルに入り、

    ll /
    ll /var
    

    の両コマンドで/tmp・/var/tmpが作られているか確認して下さい。

    • 最後に補足と今後の展望について
      /tmpと/var/tmpの"size=32m"が足りるのかについては色々調整が必要かもしれません。
      今後の展望ですが、普段の音楽再生時は/ディレクトリ(SDカード自体)をリードオンリーで再マウントするようにしようと思っています。この場合、MPDで問題になりそうなのはstate・sticker.sql・tag_cacheの3つの取扱になるかと思います。
      という訳でご質問
      ①sticker.sqlを使いますか?(私の調べた限りでは楽曲のレーティングに使われるようですが、一般的にsymphonic-mpdを使っている方はympd経由のため不要に見えます)
      ②tag_cacheを頻繁に更新しますか?(過去の使い方ですと、自分のライブラリを頻繁に更新しない場合はtag_cacheは作成済みのファイルを読込専用でも特に問題ないかと思います)
  • @sunatomo さん、お世話になります。

    再生時はSDカードリードオンリーが望ましい気がします。

    symphonic-mpdへのSD書込を減らす(その1)を実施してみました。
    再起動で起動音が鳴りました。再生も問題ないので、上手くできたようです。
    ライブラリが消えたので一瞬焦りましたが・・・

    ご質問への私の答えですが
    ①sticker.sqlは使いません。
    ②ライブラリの更新はよくあります。

  • @sunatomo さん

    興味深い記事をありがとうございます。

    symphonic-mpdでは、vm.dirty_writeback_centisecsを0に設定することで、ディスクへの書き込みを遅延させています。

    例えば、mpdは1分に1回程度の頻度でstateファイルの更新をするようですが、このような小さな書き込みはdirtyページとしてメモリ上に保持されます。

    そして実際にディスクに書き込まれるのは明示的にsyncしたタイミングとなります。
    このような設定としているため、事実上、音楽再生中にディスクへの書き込みが発生することはありません。

    Web UIで再生を停止したときなど、主要なイベントでsyncが走るようにしています。
    シェルの至る所にsyncが書いてあるのはこのような事情によるものです。

  • @sunatomo さん

    質問への答えですが、私の場合、sticker.sqlは使いません。tag_cacheは頻繁には更新しません。

    /varを削除するのに抵抗があるなら、folder2ramなるスクリプトがあります。
    https://github.com/bobafetthotmail/folder2ram

    OpenMediavaultは以前、SDカードでの運用は非推薦だったのですが
    folder2ramなプラグインのおかげでフラッシュメモリでの運用が可能になりました。

  • @hiroget9 さま
    @Cresson さま、ご質問に答えて頂き有難うございます。
    今回のネタとしては「SDカードは普段リードオンリーにしてしまえばその後何らかの不具合があって電源断をしたとしても損傷しないだろう」という目論見もあります。
    他のディストリではtag_cache他をmpdのライブラリ(ネットワーク越し)に置いているものもありますが、「必要なときだけ書き込めるようにする」ならばSDカードに置いても同じと考えて試作してみます(ネットワーク越しにするとcifsのアクセスが増えて音質に影響がある可能性も考慮し)。
    (今の構想では
     stateは/var/run/mpdへ、
     sticker.sqlは不使用、
     tag_cacheは通常はリードオンリーで運用するが更新時は一時的に書込可能にする。
    方向で進めていきたいと思います。)

    @パパリウス さま
    なるほど、書込頻度を落としているのですか。
    確かにIOへのアクセスはシステムへのコストが高いですよね。
    レイテンシを抑える目的としては確かにアリだと思います。
    パパリウスさまのこのアイデアをもう一歩先に進めて、ここでは通常運用時はSDカードへのアクセスが可能な限り不要な方向性に持っていきたいと思います。

    再度@Cresson さま
    folder2ramですか、不勉強でした。もう少し早く知っていればこっち使ったかもしれません。
    ざっと斜め読みしましたが、実態はシェルスクリプトのため、
    rc.localかmpd_event.shの末尾でこれを動かす形になりそうですね。

  • SDカードをリードオンリーにした場合の今の時点での結果をコチラに書きます。

    警告:今の時点では私の環境でも一部動作確認しか出来ていません。
    リードオンリー化しても書き込まれないだけで困ることはあまりないと思いますが、使えない機能が発生することはご理解ください。

    ◯SDカードをリードオンリーにする方法+その動作確認結果
     SDカードは実は2つのパテーションに分けられており、それぞれ"/"と"/boot"にマウントされています。
     本当ならば"/boot"もリードオンリーにするほうが良いのでしょうが、/bootは通常起動時以外は使わないと思われるのでそのままにしてあります。
     今回は"/"をsudo mount -o remount,ro / でリードオンリーにしてみました。
     結果としてはライブラリ内の音源については普通に再生できることまでは確認しています。
     ちなみに書込可に戻す場合はsudo mount -o remount,rw /でOKです。

    初期インストール状態で動作しないプラグインは「SAVE QUEUE」と「UPDATE LIBRARY」になります(理由は当然ながら/への書込が出来ないため。「SAVE QUEUE」は/var/lib/mpd/playlistsへの書込、「UPDATE LIBRARY」は/var/lib/mpd/tag_cacheへの書込が発生します。)
     ↑
     上記以外にも追加プラグインのうち、出力結果として動的にHTMLファイルを生成するものなどは軒並み動作がおかしくなります。

    ◯書込が必要なファイルへの手当方法は?
     今の所3つほど考えています。

    ①特定のファイルを設定ファイルを書き換えてtmpfsへ移動してしまう。
      mpd.confのstate_file "/var/lib/mpd/state"をstate_file "/var/run/mpd/state"に書換しましたが正常に動いているようです。
      これと同じように他にも書き換えが必要なファイルは/var/run/mpdなどに入れてしまおうと思います。

    ②標準メニュープラグインの書替
      例えば「UPDATE LIBRARY」実行時はmpc update $1というコマンドが走っています($1にはフォームで指定したディレクトリが入る)。
      これをシェルスクリプト化し、アップデートの際のみ書込権限付きで再マウントして書込終了後に再度リードオンリーで再々マウントするように修正します。

    ③folder2ramを使用して特定ディレクトリをtmpfs化
      あれからスクリプトをダウンロードして色々触り始めていますが、結構便利かもしれません。
      今は使い方を習熟中のため、少々時間がほしいところです。

    という訳でまとまりがない終わり方ですが、まずはSDカードのリードオンリーでもmpdは動作しますって話でした(ApplePlayとSpotifyは未確認ですが)。

  • SDカードのリードオンリー化、現状の進捗について

    ①起動時のリードオンリー化について
    起動時のプロセスのうち、一番最後に動作する物は/etc/rc.localであることが分かりましたので、
    これに対してリマウントしてリードオンリーにしてしまうようにしました。

    ②マウント変更用スクリプトについて
    以前紹介したmountコマンドを毎回書くのは大変だと思われますので、/usr/local/sbinにrmtrw.shとrmtro.shという名前のシェルスクリプトを起き、これを実行するようにしています。
    rmtrw.sh

    #!/bin/bash
    
    function root () {
    
      #check / partition and remount
      rwflg=`cat /etc/mtab |grep /dev/root| cut -d' ' -f4|cut -d',' -f1`
      if [ $rwflg = "ro" ]; then
        sudo mount -o remount,rw /
      fi
    }
    
    function boot () {
    
      #check /boot partition and remount
      rwflg2=`cat /etc/mtab |grep /boot| cut -d' ' -f4|cut -d',' -f1`
      if [ $rwflg2 = "ro" ]; then
        sudo mount -o remount,rw /boot
      fi
    }
    
    case "$1" in
      1)
        boot
        ;;
      2)
        root
        ;;
      all)
        boot
        root
        ;;
      *)
        echo "usage rmtro.sh 1|2|all"
        echo "this tool remount the specified directory to read and write privileges"
        echo "when you choose 1, /boot will be remounted"
        echo "     you choose 2, / will be remounted"
        echo "     you choose all , both /boot and / remounted"
       ;;
    esac
    

    rmtro.sh

    #!/bin/bash
    
    function root () {
    
      #check / partition and remount
      rwflg=`cat /etc/mtab |grep /dev/root| cut -d' ' -f4|cut -d',' -f1`
      if [ $rwflg = "rw" ]; then
        sudo mount -o remount,ro /
      fi
    }
    
    function boot () {
    
      #check /boot partition and remount
      rwflg2=`cat /etc/mtab |grep /boot| cut -d' ' -f4|cut -d',' -f1`
      if [ $rwflg2 = "rw" ]; then
        sudo mount -o remount,ro /boot
      fi
    }
    
    case "$1" in
      1)
        boot
        ;;
      2)
        root
        ;;
      all)
        boot
        root
        ;;
      *)
        echo "usage rmtro.sh 1|2|all"
        echo "this tool remount the specified directory to readondy"
        echo "when you choose 1, /boot will be remounted"
        echo "     you choose 2, / will be remounted"
        echo "     you choose all , both /boot and / remounted"
       ;;
    esac
    

    シェルスクリプトには引数を指定することでリマウントするパテーションを切り替えできるようになっています(/dev/mmcblk1、/dev/mmcblk2にちなみ数字の1と2でパテーション切替、all指定で双方処理可能)。

    ③各イベント起動シェルスクリプトの修正について
    正直、現状SDカードに記録を行うスクリプトは結構な量がありますので、最終的にアーカイブ化して提供するつもりです(現状でも全部サポートできたとは思えないところもあるため。もう少しデバッグが必要かと思います)。

    ④MPDの修正点について
    以前お聞きしたstateについてはmpd.confを書き換えして/var/run/mpd上に作成するように変更し、従来の/var/lib/mpd/stateは/var/run/mpd/stateへのシンボリックリンク化しました。
    ↑
    多分sticker.sqlを使う場合もこの方法で対応出来ると思います。mpdを停止する際にsticker.sqlをSDカードに書き出しすれば良いわけです。

    ⑤ympdのプラグインについて
    プラグインのうち、実行結果を伴うものは/var/lib/mpd/music/RAM上にhtmlファイルを出力させるようにしたほうが良いと思います。
    現状でもDASHBOARD実行時の表の元ファイル(jsonファイル)やグラフの元ファイル(svgファイル)がこのフォルダに生成されていますので。

    ⑥現状の課題点について
    動作確認を行っている状況ですが、PlaybackのConsumeが毎回オフになってしまいます。

    ⑦folder2ramについて
    ブラウザのキャッシュのせいだと思いますが、これを使ってプラグインからログを出力させた場合はなぜか出力結果が表示されない結果に悩まされてしまいました(sshのシェルでは間違いなくファイルが生成されているのに....)。
    という訳で、今のところは使っていません。

  • 🍊 @sunatomo さん

    PlaybackのConsumeは、/var/lib/mpd/stateファイルに保存されます。
    mpd停止時にうまく書き出されていないということかなと思います。

  • @パパリウス さま
    stateファイルにその手の情報書き込まれているとは思いませんでした。よく中身を見たら、random・repeatやcrossfadeもパラメータにありますね。
    実はmpd起動前のシェルスクリプトstateファイルは毎回touchコマンドで生成するようにしていたので、終了時にバックアップする様に修正してみます。

  • ラズパイで電源断時に何か実行したいときには?

    SDカードのリードオンリー化ですが、今の所2つほど不具合が発生しています。
    せめて①だけは潰しておきたいと思いますので、公開まではもう少しお待ち下さい。

    ①ympdのハング
    ympdのアクセスがない際に自動的にプロセスが終了するのですが、HTTPポートへのアクセスが復活した際の再起動が複数プロセスが重なった状態に陥いり、この場合起動できなくなる場合がある。
    (ympdの80番ポートはsystemdのympd.socketが監視しており、これがアクセスがなくなった時点でympd.serviceを停止する。
    上記の現象が発生した場合、一定時間の自動ロックが働くようでympd.socketを一旦再起動しないとympd.serviceは起動しなくなります。)

    ②avahi-daemonのハング
    avahi-daemonがなぜが失われる場合がある。journalctlにも明確なログがなく、現在調査中。

    というわけで、現状のツナギで今回は本体再起動・停止時に何か実行したいときにはどうする?をお送りします。
    この技はsystemdがインストールされている場合のみ動作します(従来のinit.d形式の場合、rcS.dにKで始まるシェルスクリプトを配置する形で対応するはず)。

    /lib/systemd/system-shutdownに任意のシェルスクリプトを置くことで、電源断の最後に動作させたいプログラムを指定することが出来ます。
    本当ならば.serviceを真面目に書いたほうが良いらしいですが、上記の手抜きでも私のニーズでは大丈夫でした。

    これの必要な目的としてはfake-hwclockを本体電源断前に走らせる必要があったからでした。
    ラズパイはPCと異なりRTCを内蔵していないため、電源断後の再起動時はntpなどでネットワーク経由で時刻を取得するまでは時刻が1970年1月1日の0:00〜にリセットされてしまいます。

    これを防止するための簡易的な機能としてfake-hwclockというものがあり、これとcron.hourlyの利用で1時間に一度ラズパイの時刻を/etc/fake-hwclock.dataに保存して、再起動時はこの時刻をまずは設定することで再起動時の時刻ズレを低減するようにしています。

    今回SDカードをリードオンリーにした際、fake-hwclockがうまく動作していない
    (そりゃそうだ、/etcディレクトリもSDカードだから書込不可にしてしまった)
    ことがjournalctlのログで分かりましたので、
    上記の場所でfake-hwclock saveを行うスクリプトを追加したところ再起動後のjournalctlの時刻が比較的早めに現時刻に近い状態で記録されるようになりました。
    ↑
    気持ちの問題ですが、cron.hourlyで行っているfake-hwclock記録は上記の対応してしまえば、止めても良いかもしれません。

    おまけ:symphonic-mpdでは通常実行されるcron.daily・cron.weekly・cron.monthlyはanacronがインストールされていないため動作しません。

  • jounalctlの邪魔なpamによる認証メッセージを消したい
    ympdとavahi-daemonのハング対応のためjounalctlとのにらめっこをしているのですが、その中で鬱陶しい以下のメッセージを消したいと思いました。

    smpd sudo: pam_unix(sudo:session): session opened for user root by (uid=0)
    smpd sudo: pam_unix(sudo:session): session closed for user root
    

    このメッセージ、sudoを実行した際の認証(pam)が吐くメッセージのため、セキュリティのことを考えるならば残したほうが良いのですが、
    シェルスクリプトでのコマンド動作時にも表示されて非常に煩わしい。
    「家庭内でプライベートネットワーク下でラズパイ走らせているなら表示しなくても良いだろう」ということで消してしまいました。

    警告:今回ご紹介の方法については失敗した場合はsymphonic-mpdの正常な起動ができなくなる恐れ+当該ファイルの編集が出来なくなる可能性がありますので、慎重にファイルを編集して下さい。

    やり方

    • /etc/pam.d/sudoをエディタで編集します(当然、ユーザはrootのファイルのためエディタはsudoで開いて下さい)。

    • 先頭行の#%PAM-1.0と@include common-authの間に以下の行を入れて下さい。

    session [success=1 default=ignore] pam_succeed_if.so service in sudo quiet uid = 0
    

    全部表示させるとこんな感じ

    #%PAM-1.0
    
    session [success=1 default=ignore] pam_succeed_if.so service in sudo quiet uid = 0
    
    @include common-auth
    @include common-account
    @include common-session-noninteractive
    
    • 書替え後保存し、再起動してください。

    効果の程はこんな感じ(rc.localでchrtによるリアルタイム優先度をプロセス毎に設定し直ししているところになりますが、pamのメッセージが消えています。本来ならコマンド1行毎にあの煩わしいメッセージが付属します)。

    Oct 31 21:58:25 smpd sudo[599]: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/chrt --fifo -p 99 556
    Oct 31 21:58:25 smpd sudo[600]: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/chrt --idle -p 0 14
    Oct 31 21:58:25 smpd sudo[615]: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/chrt --idle -p 0 15
    ・ 以下続く...
    ・
    ・
    
  • @sunatomo さん

    情報ありがとうございます。

    これは助かりますねえ!
    早速、設定変更させていただきましたがジャーナルがこんなにすっきりしているのを見るのは久しぶりです😆

    次のSDイメージにはこの設定を反映させたいと思います。

  • SDをリードオンリー化する(公開版)

    不具合をなんとかしたいと思ってスクリプトの内部を色々見てみましたが、
    現状では先週の土日に上記の現象が発生してからはとりあえず問題なく動いているため公開いたします。
    私の修正したスクリプトは以下の通りZIPファイル化しましたので、これをラズパイの/runディレクトリなどで解凍して差替して下さい。
    smpd-readonly.zip
    編集+新規作成したファイルは以下の通り

    ・/etc/mpd.conf 編集
     (sticker.sql・stateファイルの場所を /var/run/mpd 配下に変更)

    ・/etc/rc.local 編集
     (readyサービス動作時の最後で/usr/local/sbin/rmtro.shを実行しSDカードのリードオンリー化)

    ・/lib/systemd/system/mpd.service 編集
     (mpd起動前と終了時にstate・sticker.sqlをレストア+バックアップするスクリプトの記述を追加)

    ・/lib/systemd/system-shutdown/run-in-shutdown.sh 新規作成
     (電源断前にSDカードを書込許可にし、fake-hwclock saveを実行して現在時刻を記録)

    ・/usr/local/sbin/rmtro.sh rmtrw.sh 新規作成
     (リードオンリー・書込許可でSDカードを再マウントするためのバッチファイル)

    ・/home/pi/util-latency.sh util-restore.sh 修正
     (内部を見たところSDカードへの書込があるため、rmtrw.sh・rmtro.shの処理を追加)

    ・/home/pi/configs/mpd_post.sh mpd_pre.sh 新規作成
     (systemdでmpd.serviceを開始する前に実行されるのがmpd_pre.sh・終了時に実行されるのがmpd_post.shとなります。
     mpd_pre.shが/var/lib/mpdのstateとsticker.sqlを/var/run/mpdへレストア、mpd_post.shは逆にバックアップを行います。)

    ・/home/pi/configs/shairport_disable.sh spotify_disable.sh 修正
     (shairport_sync並びにspotifydを無効化した場合、/home/pi/configsにフラグファイルを生成しますが、
     これのためにSDカード書込が必要なための修正です。)

    ・/home/pi/misc/edit_fstab.sh inplace_update.sh kernel_install.sh ympd_event.sh
     (SDカードへの書込が必要なための修正。)

    ・/home/pi/plugins/
     少し詳細に説明します。
     今回のSDカードリードオンリー化のため、.plugin.jsonも書き換えしました。

    具体的には「UPDATE LIBRARY」の際に従来は"mpc update"コマンドだけを実行していたのですが、
    今回"mpc_update.sh"というシェルスクリプトを用意して、"mpc update"コマンド実行前にSDカード書込を許可しています(処理終了後にSDカードをリードオンリー化します)。
     この変更に伴い、mpcがライブラリを更新している間にどうしてもシェルスクリプトが待ちの状態になるため、
    「UPDATE LIBRARY」実行時はHTML出力有りに仕様変更しました。

    パパリウスさまご指摘の"systemd-run"使用により、従来通りバックグラウンドで更新作業が実行されます。

    NASの全ディレクトリを更新する際は非常に時間がかかるかと思いますが、
    特定ディレクトリ内にアルバムを追加しただけの場合は一瞬で終わりますのでご理解頂きたく思います。
    (これが嫌な場合はtag_cacheを書込可能なディレクトリに置くしか無いと思います)。

    また、プラグインで各シェルスクリプトが実行結果として出力するHTMLは/var/lib/mpd/music/RAM上に生成するように書き換えしています。

    長くなったので分けます。

  • ・インストール方法
     先の投稿に付いていたZIPファイルを自分のPCにダウンロードして下さい。
     ラズパイはsudo systemctl stop mpd.service でMPDを止めておいて下さい。
     停止しているかはsudo systemctl status mpd.serviceで確認して下さい。

    以下のコマンドでstateファイルのバックアップ化+RAMディスク側のstateファイルへのシンボリックリンク作成を行います。

    cd /var/lib/mpd
    mv state state.bak
    ln -s /var/run/mpd/state state
    

    ZIPファイルを解凍し、中身を確認しながら新規作成もしくは編集で追記事項を各ファイルに入れてください。
    (PC側で一旦ZIPファイルを解凍し、中身を見ながらファイルを複写する場合はfilezillaで書き込むのが簡単でしょう。
    書替えの場合はPC側で当該ファイルをエディタで表示させて、ラズパイのSSHクライアント側ではnanoエディタを開いて左右に並べて表示させてみて下さい。)
     ちなみに/home/pi/configs/shairport_disable.sh spotify_disable.shの2つは以前にご紹介した「ApplePlayとSpotifyを無効化する」を行っていない方は不要になります。

    インストーラについては要望が多いようならば対応考えますね(今回は流石に書替えが多く手動での編集はかなり大変だと思いますので)。

    ・SDカードリードオンリーによる利点+不利益点
     ◯利点
      □システムがハングした際も安心して電源断を行うことが可能
       (実際には再マウントで書込可能状態になっている可能性はありますが、
       確率的にはかなり低いでしょう。)
      □SDカードへの書込回数減少による長寿命化
     ◯不利益点
      □MPDを直接制御するソフトウェア(Cantata等)使用時にいくつかの操作が出来ない
       ライブラリ更新やプレイリス編集できなくなります。
      □SSH経由によるファイル編集時にいちいちSDカードの再マウントをする必要がある。

  • @sunatomo さん

    mpc updateの完了待ちが必要となる件ですが、
    systemd-runがうまく使えないでしょうか。

    バックグラウンドで実行させたいジョブをympdからキックするのに時々使っています。

  • @パパリウス さま
    systemd-runですね。有難うございます。
    裏でググって調べましたが、一発動作もできますし、タイマー起動も出来るというかなりのスグレモノですね。
    (私事ですがsystemdは食わず嫌いで、symphonic-mpdの内部に触れるまでは全然不勉強でした。)
    という訳で、あっさりmpc updateの結果の出力対応は止めてしまうことにしましょう。
    取り急ぎ書換場所をソースで示します。

    .plugin.json

      {
        "menu" :"UPDATE LIBRARY",
        "active" :"yes",
        "icon" :"retweet",
        "form" :"/plugins/demo/update_library.html",
        "command":"systemd-run /home/pi/plugins/mpc_update.sh",
        "output" :"",
        "success":"Library update started",
        "error" :"error!"
      } ,
    

    mpc_update.shの方はもう少しの間ログ代わりにHTMLを吐かせておきます
    (とりあえず正常に動作したことが確認できるまでは)。

  • NAS Settingの結果をもう少し対話型にしてみる
     皆さまご存知の通り
    symphonic-mpdではNASの設定をympdの「SETTINGS」で表示されるフォームから入力して「SAVE」ボタンを押すことで行うことが出来ます。

    今回はこのNAS Settingで実行されるシェルスクリプトをもう少し実行結果をわかりやすく「説明文を追加したもの」を提供します。
     あと、pathの入力文字列でホスト名を検知し、自動的にpingでそのホストからの応答があるか事前確認するようにしてみましたので、人柱上等な方はちょっと動作を確認してみて下さい。
     (一応我が家のQNAPのNASではipv4・ipv6ともに確認してこの状態でエラーチェックは通っています。)
     また、私が追記した説明部分は「怪しい英文」のため、そちらのご指摘も喜んで受けます。
    edit_fstab.png

    書換方法:filezillaなどでファイルを複写して下さい。パーミッション・ユーザは元のファイルと合わせて下さい(パーミッションは755・ユーザはpi/pi)。

    /home/pi/misc/edit_fstab.sh
    2019-11-09 9:40差替済

    #!/bin/bash
    
    mpc stop
    umount /var/lib/mpd/music/NAS
    
    LOG=/var/lib/mpd/music/RAM/.nas_setting.log
    
    # work dir
    dst=/tmp/cifsdst
    mkdir $dst
    
    # detect protocol
    user=`echo $2 | tr -d " "`
    pass=`echo $3 | tr -d " "`
    opt="cache=none,iocharset=utf8,username=$user,password=$pass"
    
    echo "updating fstab start!!" > $LOG
    
    hst=`echo $1 | sed -E 's/^\/\/([^/]+).+/\1/g'`
    
    echo " Checking ping reply to ${hst}" >> $LOG
    
    /bin/ping -c 1 -W 1 ${hst} > /dev/null
    if [ ! $? = 0 ]; then
      echo "  !!!${hst} has not reply via ipv4" >> $LOG
      /bin/ping6 -c 1 -W 1  ${hst} > /dev/null
      if [! $? = 0 ]; then
        echo "  !!!${hst} has not reply via ipv6" >> $LOG
        echo "!!!Aborting the process!!!" >> $LOG
        exit 1
      fi
    fi
    echo "  Ping successed" >> $LOG
    echo "" >> $LOG
    
    echo " Checking cifs security mode and protocol version" >> $LOG
    exopt=""
    declare -a aver=("1.0" "2.0" "2.1" "3.0")
    for e in ${aver[@]}; do
      mount -t cifs $1 $dst -o $opt,sec=ntlm,vers=${e} >/dev/null 2>&1
      if [ $? = 0 ]; then
        exopt=sec\=ntlm,vers\=${e}
        umount $dst
      fi
    
      mount -t cifs $1 $dst -o $opt,sec=ntlmssp,vers=${e} >/dev/null 2>&1
      if [ $? = 0 ]; then
        exopt=sec\=ntlmssp,vers\=${e}
        umount $dst
      fi
    done
    
    if [ "$exopt" = "" ]; then
      echo "  !!!Can not resolve the security mode or protocol version." >> $LOG
      echo "  Aborting the process!!!" >> $LOG
      rmdir $dst
      exit 1
    fi
    
    echo "  security mode and protocol version: $exopt" >> $LOG
    exopt=,$exopt
    
    sync
    
    # detect best rsize prepare
    declare -a arsize=("7300" "16060" "32120" "61320" "129940")
    
    fioconf=/home/pi/misc/fio.conf
    testfile=
    bestrsize=
    bestbw=0
    bestctx=1000000
    
    declare -a arsize2=()
    declare -a abw=()
    declare -a alatency=()
    declare -a actx=()
    declare -a amajf=()
    declare -a aminf=()
    
    mount -t cifs $1 $dst -o $opt,$exopt,wsize=4096 >/dev/null 2>&1
    dd of=$dst/rsize_test_dummy bs=4k count=0 seek=2500
    sync
    
    umount $dst
    
    echo "" >> $LOG
    echo " Checking best rsize" >> $LOG
    echo "" >> $LOG
    echo "  rsize       BW    CTX  latency" >> $LOG
    for e in ${arsize[@]}; do
      mount -t cifs $1 $dst -o ro,$opt,$exopt,rsize=${e} >/dev/null 2>&1
    
      # fio start
      out=`fio --readonly -filename="$dst/rsize_test_dummy" --output-format=terse $fioconf | cut -d';' -f7,8,16,90,91,92`
    
      #echo "RSIZE ${e}:$out" >> $LOG
    
      # detect best rsize
      bw=`echo $out|cut -d';' -f1`
      latency=`echo $out|cut -d';' -f3|cut -d'.' -f1`
      ctx=`echo $out|cut -d';' -f4`
      majf=`echo $out|cut -d';' -f5`
      minf=`echo $out|cut -d';' -f6`
    
      arsize2+=( ${e} )
      abw+=( $bw )
      alatency+=( $latency )
      actx+=( $ctx )
      amajf+=( $majf )
      aminf+=( $minf )
    
      printf "%7d %8d %6d %8d\n" ${e} $bw $ctx $latency >> $LOG
    
      if [ $bw -gt $bestbw ];then
        bestbw=$bw
        bestrsize=${e}
      fi
      sudo umount $dst
    done
    
    i=0
    #echo "rsize  bw  lat  ctx  majf  minf" >> $LOG
    for e in ${arsize2[@]}; do
      count=0
      for ((ibw = 0; ibw < ${#abw[@]}; ibw++)){
        if [ ${abw[i]} -lt ${abw[ibw]} ];then
          let count++
        fi
      }
      if [ $count -lt 3 ];then
        count=0
        for ((ilat = 0; ilat < ${#alatency[@]}; ilat++)){
          if [ ${alatency[i]} -gt ${alatency[ilat]} ];then
            let count++
          fi
        }
        if [ $count -lt 3 ];then
          count=0
          for ((ictx = 0; ictx < ${#actx[@]}; ictx++)){
            if [ ${actx[i]} -gt ${actx[ictx]} ];then
              let count++
            fi
          }
          if [ $count -lt 3 ];then
            if [ "$bestbw" = "" ];then
              bestctx=${actx[i]}
              bestbw=${abw[i]}
              bestrsize=",rsize=${e}"
            elif [ ${actx[i]} -lt $bestctx ];then
              bestctx=${actx[i]}
              bestbw=${abw[i]}
              bestrsize=",rsize=${e}"
            fi
          fi
        fi
      fi
      #echo "${e} ${abw[i]} ${alatency[i]} ${actx[i]} ${amajf[i]} ${aminf[i]}" >> $LOG
      let i++
    done
    
    # clean up
    mount -t cifs $1 $dst -o $opt,$exopt,rsize=4096 >/dev/null 2>&1
    rm "$dst/rsize_test_dummy"
    umount $dst
    rmdir $dst
    
    # edit fstab
    target=/etc/fstab
    nas="$1 /var/lib/mpd/music/NAS cifs ro,noauto,x-systemd.automount$exopt$bestrsize,$opt"
    
    echo "" >> $LOG
    echo "  best bandwidth : $bestbw kB/sec" >> $LOG
    echo "" >> $LOG
    echo "  fstab setting  : $nas" >> $LOG
    
    sed -i.bak -e "/# NAS Setting/{n;d}" $target
    sed -i -e "/# NAS Setting/a $nas" $target
    sync
    
    echo " Restarting mpd and mounting NAS with new setting" >> $LOG
    
    systemctl stop mpd
    systemctl daemon-reload
    mount -a
    systemctl start mpd
    
    mountpoint /var/lib/mpd/music/NAS
    ret=$?
    echo "" >> $LOG
    if [ $? -eq 0 ]; then
      echo "NAS setting successed" >> $LOG
    else
      echo "Failed to mount NAS with new setting" >> $LOG
    fi
    sleep 2
    rm $LOG
    
    exit $ret
    
    

    なお、私の以前の投稿のsymphonic-mpdのSDカードリードオンリー化を実施している場合、
    下の方にある、sed -i.bak -e "/# NAS Setting/{n;d}" $targetの前行にrmtrw.sh 2を、
    syncの後行にrmtro.sh 2を挿入する必要があります。

    今後の展望ですが、pingによるエラーチェックをすり抜けたあとでcifsのバージョンチェックのためのマウントに失敗した場合のエラーを検知出来ていないため、
    これに対応させたいと思っています。

    途中でexopt=""を追加したことにより対応出来ました。

  • @sunatomo さん

    これは素晴らしいですね!
    よろしければSDイメージに同梱させてください☺

    それからsuccessedの誤植、edit_fstab.shにも残っていましたね。。。お恥ずかしい😱
    ympd側も修正しなければNAS設定の終了を正常に検知してくれませんので、次のバージョンで一緒に直したいと思います。

  • @パパリウス さま
     SDカードイメージへの同梱については、パパリウス様のご厚意にお任せいたします(笑
     当該スクリプトは私なりに中身を確認して、どこで何をやっているかは把握した状態で途中のコメントや処理を追加していますが、
    足りない部分はあると思いますので改変も全然OKです。
    (と、これを書きながら思ったのですが、pingでのホストへのネットワーク接続チェックは行っていますが、
    どちらのプロトコルで成功したかは少しわかりにくい状態ですね。)
     エラー処理については現状のままでも十分アリかと思っています。
    (ただ、現状の標準だと途中で処理が止まったことがわかりにくいため、
    エラー表示を出力してほしいという趣旨で直しています。)