読者です 読者をやめる 読者になる 読者になる

macbook pro で 月曜 junk をとりたいいっ - shell script & launchd (2/2)

shellscript radiko tech

radiko を予約録音する事例について.

前回はレコーディングする shell script について書きました.

今回は,レコーディングの "タイマー" の部分です.

先のエントリーでも書きましたが,
ここでは cron ではなく,launchd/launchctl によるスケジューリング制御を試してみることにしました.

cron を launchd で定義すると?

まず結論めいたところから.

話がより具体的な方が伝わり易いかと思うので,
ここでは 'junk 伊集院光 深夜の馬鹿力' を例に*1

cron でのこんな定義, ;

0 1 * * 2  ~/radiko/radiko.sh TBS 120 -t "深夜の馬鹿力" -a "伊集院光" -g "radio" -A "JUNK 伊集院光の馬鹿力" >/dev/null 2>&1

これが,launchd の plist だとこうなるんじゃないかと思います.;

面倒そうですね...w

launchd の key の意味は cron のソレと並べて見れば何となく分かると思います*2
ここでは個々の詳細な説明は省きたいと思います.

個人的に,記載方法と key の意味については,以下のサイトがとても参考になりました.ありがとうございます.;

launchd の準備

launchd の定義は plist になります*3

ということで xml. ちょいと面倒ですねw

あるモノで出来るだけスマートに?こなす方法はないかかしら,と悶々としていたら,ありました.
ASCII 形式の plist ファイルから XML 形式の plist ファイルを作成するのです.

ワークフローが大まかにこんな感じでしょうか.;

  1. ascii 形式の plist 作成.
  2. 1 で作った plist を plutil でコンバート.
    →ここで launchd の plist が出来ます.
  3. 2 の plist のセッティング
  4. plist のロード

以下具体的な内容を. そしてここでも引き続き,上述 junk 録音のケースで話を進めます.

使うツール

2 つ.;

  • エディター (ex. テキストエディット.app)
  • ターミナル (ex. ターミナル.app)

いずれも,いつも使っているもので良いです.この為に別途ソフトウェアを導入したりする必要はありません*4

作り方

まずは plist を作るまでです.
ステップは 3 つ.

  1. ascii 形式の plist を用意.
  2. 1 を xml 形式の plist へコンバート.
  3. 2 でできた plist の確認.

以下詳細.

  1. エディタで ascii 形式の plist を用意します. ここでは最終目的とする xml 形式 plist のひな形をつくる程度の感覚でいます.
    内容はこんな感じになると思います.

    この作業で注意する点は,key 'Lavel'.
    これは最終的に plist のファイル名になる,ということは気にしておいてください.
    この 'Lavel' の付け方について,ちょっとおせっかいな事を言えば 2 つ.もちろん msut ではないです."よろしかったら" 程度の個人的なお勧めです,;

    • mac os のお作法に出来るだけ倣った方が良いかなぁと.こんなかんじ?*5
    • 迷ったら,番組メールアドレスのアカウントを使うと便利.*6

    出来たら,これを適当な適切な場所に plsit として保存します.ここではあくまで作業上仮の plist ファイルとしてますので tmp.plist としました.ファイルの名前も保存場所も任意,作業しやすいよう,適当で良いです.

  2. ターミナルで ascii 形式 plist を xml 形式 plist にコンバートします. こんな感じかと思います.;

     % plutil -convert xml1 ~/radiko/temp.plist -o ~/radiko/example.radiko.tbs1.baka.plist *7
    

    フォーマットは plutil -convert xml1 {plist1} -o {plist2} となりますね.

    {plist1} はコンバート"元".1 で作った,いわゆる scii 形式の xml で定義した方.
    {plist2} がコンバート"先".launcd としての plist.

    {plist2} として指定するファイル名は 1 で述べたように,'Lavel' key と同じ文字列を.これに拡張子 "plist" が付きます.
    上のコードの例ですと, 'Lavel' は "example.radiko.tbs1.baka" にしましたので,ファイル名は "example.radiko.tbs1.baka.plist" となります.

  3. 生成された plist をエディター開いて,内容を確認してください. 必要に応じ,微調整をしておわり.
    最終的には冒頭に挙げた感じになると思います.

launchd の plist の使い方

launchd のための plist "example.radiko.baka.plist" ができました.

次にこの plist をロード(登録)して,定義したスケジュール通りに動いてもらうようにします.

ステップは 2 つ.
いずれもターミナルでの作業となります.;

  1. plist を "~/Library/LaunchAgents" に置く.
    ファイルのパーミッション,chmod 644 に.
  2. plist を load する.

以下詳細です.

  1. plist を "~/Library/LaunchAgents" に置きます.
    先の launcd の plist "example.radiko.baka.plist" を "~/Library/LaunchAgents" に置きます.

    plist を設置する場所は仕様的に決まっていて他にもあります.
    バリエーションは 5 つあって,それぞれ目的によって使い方が異なります.

    ここでは上述パスにしました.

    USER_NAMEのログインユーザーのみに提供するサービス(USER_NAME以外のユーザーには提供されない)
    /Users/USER_NAME/Library/LaunchAgent
    例:フォルダアクションスクリプトのフォルダ監視サービスの起動
    例:SafariとMobileMeの同期サービスの起動

    あくまで個人的な閉ジタセカイノモノという扱いで管理したかったので.
    この点についても各自個人の流儀で良いと思います.もう一つの候補として "/Library/LaunchAgent" でもいいとは思います.

    そして,置いたら plist に対しパーミッションを設定しておく必要があると思います.
    644 で宜しいそうです

     % chmod 644 ~/Library/LaunchAgents/example.radiko.baka.plist
    

    となりますか?
    まぁ閉ジタセカイの中の話なので景気良く 777 でもいいかもしれませんが.

  2. plist を load します.
    ターミナルで作業します.
    以下の要領でコマンドを叩きます.

     % launchctl load ~/Library/LaunchAgents/example.radiko.baka.plist
    

    launchctl というコマンドを使います.
    launchctl が何かについては,まぁ wiki か,この辺りが掴みやすかったです.数行ですが.

    ということでおしまいです.

自分の plist がきちんと load されているかを確かめるには以下;

% launchctl list

バッと登録されている launchd が表示されると思います.

また,plist を変更し,その内容を反映したい場合は,
一旦 unload してから再び load し直す必要があるようです.
今回の例ですと ;

% launchctl unload ~/Library/LaunchAgents/example.radiko.baka.plist && launchctl load ~/Library/LaunchAgents/example.radiko.baka.plist

とこんな感じ.
でも,何か unload & load しなくても,何か反映されるような気がするのは,気のせい?

あ,流れながら参照先挙げてきましたが,
何より man は目を通しておくのは前提でお願いします.まぁ,挙げてきた参照先ページできちんと紹介されているかと見ていたので,そこからオフィシャルのドキュメントに辿れるとは思います.

特に,ここ "Daemons and Services Programming Guide Scheduling Timed Jobs" はとても参考になると思います.
「ありえない」言う人は,"Scheduling Timed Jobs" のセクションから手をつけると,実用的なうえ分り易く,ノレると思います.

はいっ.有るモノで,お金を掛けずに radiko のスケジュール予約録音する方法は以上となります!!

cron と launchd ,どっち?

終わりに,これが個人的に気持ち悪かったポイントでちょっと考えたので,備忘録の意も込めて,自分のために軽くメモを残しておこうと思います.

色々見て,触って,考えてみて,結果思ったのは,"どっちでもいんじゃないかなぁ" と.
"慣れ" とか "好き" とか "何となく" 等と言った,実に情緒的なレベルで決めてもいいんじゃかなろーかと.
少なくともココでやろうとしている程度ならば.

そう,もちろん技術的な視点ではない :)

… launchd がきめ細かな設定ができるとはいえ cron の御手軽さも捨てがたいものはありますな(無理に lanuchd を使わなくてもいいだろうという話もある)

自分も全くもって同意.

じゃぁさぁー...,と...

どっちでもいいと言ってるのに,どうして cron ではなく launchd にしたか

単純に "os として launchd が推しみたいだから".
ただそれだけです.そう単なるミーハー.

cron と launchd の (個人的に知りたかった) 関係

mac os における launchd の位置づけについては,ココとかソコとかで長々と詳しく述べられてますが...
要はこういう事だろうと思います.;

cronもlaunchdの子プロセス

たった一言でいい(笑
この表現が一番ピンときたかな :p

オチ(課題)

で.
オチです.

If you schedule a launchd job by setting the StartCalendarInterval key and the computer is asleep when the job should have run, your job will run when the computer wakes up. However, if the machine is off when the job should have run, the job does not execute until the next designated time occurs.
All other launchd jobs are skipped when the computer is turned off or asleep; they will not run until the next designated time occurs.
Consequently, if the computer is always off at the job’s scheduled time, both cron jobs and launchd jobs never run. For example, if you always turn your computer off at night, a job scheduled to run at 1 A.M. will never be run.

はい. 今回のケースですと,
毎週月曜日は,27時までマシンの前から離れてはいけないことになりました.
いや,それだけではありませんっ.あなた自身はおろか,マシンさえも眠りに入れてはいけませんっ.あっはっはっはっはっ.

ということでこの度, テクノロジーは,私たちの生活を便利にするどころか,脂っこい体育会系的発想に不経済キラキラなライフスタイルを提供してくれることになりましたとさ(嘲笑 *8

次はこの辺りの話になりますかね.

はい,おぉしぃまいっ.

*1:radiko 録音を考えてる人って,月曜 junk リスナー率何気に高いような....ま,ウチもその一人で今回の作業のもっとも大きな動機づけになっていたりするのですが.

*2:この例での key はあえて最小限にしています."まずは必須アイテム,そして次に使いたいアイテム",という考え方で定義しています.分り易さ優先で,"記載しない場合セットされるデフォルト値で構わない" とされる key は定義しないようにしてます.本当ならもっとキチンと定義すべきなのかもしれません...

*3:という言い回しで正しいですか?

*4:もちろん他の方法もあります.例えば,お金で解決できる人は 'Lingon' 買うのが良いと思います.

*5:基本的に各自好きに付けて良いのですが,ルール的にだけではなく,個人的な管理運用的にもちょっと便利になるのではなかろうかと.この辺りのネーミングルールについて,以前良いドキュメントを参照した記憶があったのですが,どこか忘れちゃったです.すみません....ちょっと気持ち悪い.

*6:お勧めは {os への自分のログインアカウント}.radiko.{番組メールアドレスのアカウント部}.これで重複する可能性はぐっと低くなるかと...

*7:"-o ..." 以降を指定しない場合は,上の例であれば "tmp.plist",それ自身に上書きします.もとの内容は消えます.ここでは ascii 形式で書いた plist をそのままにしておきたかったのでこうしました.好みですね.

*8:まぁこんな感じでで満たされない現実に逃げる方法もありますが.