ラベル crontab の投稿を表示しています。 すべての投稿を表示
ラベル crontab の投稿を表示しています。 すべての投稿を表示

2013年3月3日日曜日

フォルダの背景の花粉情報予測マップ画像表示の自動化 (スクリプト編)

前の記事でフォルダの背景に花粉情報予測マップ/地図の表示を毎日、自動でできるようにしました。
ただ、読んでいただけた方にはわかると思いますが、結構手順が長いです。ブログを書くのも相当時間がかかりました。Automatorはある程度決まったことを行うのは便利ですが、細かいところを弄ろうとすると冗長な感じがします。

そこで、今回は、手順が短くなることを期待してスクリプトベースで、花粉マップを更新したいと思います。スクリプトは、シェルスクリプトとAppleScriptを考えています。

花粉マップを表示するフォルダは、Automatorの時と同じくtest、花粉マップをダウンロードするフォルダは、test/kafunにします。

例によって、流れは以下のとおりです。
  1. 花粉マップ画像をダウンロード
  2. AppleScriptで花粉マップ画像をフォルダの背景に設定
  3. crontabで自動実行をスケジュール

1. curlコマンドで花粉マップ画像をダウンロード

できるだけMac OS Xにはじめから入っているコマンドで実行したいと思います。花粉マップ画像のダウンロードはcurlコマンドを用います。フォルダ(ディレクトリ)をダウンロードする場所に移り、古い花粉マップを別名で保存しておき、ダウンロードします。
次のようになります。

cd /Volumes/Disk1/DL/test/kafun
mv -f pollen_mesh_large.jpg pollen_mesh_large.jpg.old
curl -sO http://season.tenki.jp/component/images/pollen_mesh_large.jpg


2. AppleScriptで花粉マップ画像をフォルダの背景に設定

AppleScriptは以下のようになります。


tell application "Finder"

set theFolder to "/Volumes/Disk1/DL/test" as POSIX file

set theFile to "/Volumes/Disk1/DL/test/kafun/pollen_mesh_large.jpg" as POSIX file

open folder theFolder
set background picture of the icon view options of window 1 to theFile
end tell


上記のApplescriptをシェルからosascriptコマンドで実行します。理由は、1.と2.のスクリプトを一つのファイルにしたいためです。

1.と2.のスクリプトをまとめて整形したものが以下です。AppleScriptの2回目のset background pictureは前回の記事と同じで、対象のフォルダを開きっぱなしにしておくと設定がすぐに反映されなかったためです。


#!/bin/sh

TARGET="/Volumes/Disk1/DL/test"
DLURL="http://season.tenki.jp/component/images/pollen_mesh_large.jpg"
DLFolder="/Volumes/Disk1/DL/test/kafun"
IMG=`basename "$DLURL"`
IMGPath="$DLFolder/$IMG"

cd "$DLFolder"
if [ -e "$IMG" ]; then
    mv -f "$IMG" "$IMG.old"
fi
curl -sO "$DLURL"

cat <<EOF | osascript >/dev/null
tell application "Finder"
    set theFolder to "$TARGET" as POSIX file
    set theFile to "$IMGPath" as POSIX file
    open folder theFolder
    set background picture of the icon view options of window 1 to theFile
    set background picture of the icon view options of window 1 to theFile
end tell
EOF


以上を、ここでは、/Volumes/Disk1/DL/test/kafun/kafunbg.shとして保存します。
また、以下のコマンドで実行権を付けます。

$ chmod a+w /Volumes/Disk1/DL/test/kafun/kafunbg.sh


3. crontabで自動実行をスケジュール

2.で作成したシェルスクリプトが実行されるのを確認します。
特に問題ないようでしたら、自動実行できるようにします。
最近はlaunchdで自動実行するのがいいようですが、ここではcrontabを使います。
growlnotifyをiCalのアラーム代わりに使ってみるの(3)も参考にしてください。

crontab -lで現在の設定を確認した後、以下のコマンドで、シェルスクリプトを追加してください。


$ crontab -e

デフォルトのエディタ(通常はvim)で、crontabの定義画面が起動します。

朝6時55分に実行する場合は、以下のようになります。

55 6 * * * /Volumes/Disk1/DL/test/kafun/kafunbg.sh

既に他の定義がしてある場合は、最後の行にでも追加するといいと思います。
そのうち、launchdでの説明も書きたいですが、ちょっと時間がかかりそうです。

2013年1月13日日曜日

.MaxOSX/environment.plistからPATH変数が読まれないことへの対処 [一部修正]

去年(2012年)の前半頃(まだ、Snow Leopardを使っていた頃)のことですが、NerdToolやcrontabから起動しているスクリプトの一部が動かなくなっていることに気づきました。


暫定的な対応


動いているスクリプトと動かないスクリプトを見比べると、スクリプトをフルパスで起動したり、PATH環境変数を再設定しているものは動いていました。PATH変数が何らかの原因で設定されていないようです。とりあえずスクリプト内の動かなかったコマンドが起動できるようにPATH変数を修正して動くようにしていました。
例えばこんな感じです。

修正前
#!/bin/sh
site_check.sh

~/bin ディレクトリにsite_check.shスクリプトを置いていますので、HOME変数を追加します。HOME変数は設定されていました。また、このスクリプト内から/opt/local/binあるコマンドを起動できるようPATHに追加します。

修正後
#!/bin/sh
PATH=/opt/local/bin:$PATH
$HOME/bin/site_check.sh

原因と対応

PATH環境変数が設定されなくなった原因は、Mac OS Xのセキュリティアップデートでの仕様変更のように思われる(どこかで読んだ記憶がある)のですが、ソースを見つけられませんでした。Security Update 2012-002による変更で、ログインした際に、~/.MacOSX/environment.plist内のDYLD_*変数を読み込まないようにしたという記述はあるのですが、PATH変数については記載されていませんでした。[Appleのリンク]

対処については、

  1. アプリケーション内でのInfo.plistでのLSEnvironmentキーを設定する方法
  2. /etc/launchd.confを作成する方法
  3. 個別のアプリケーション毎にlaunchd.plist (ファイル名は別にするようです)を記述する方法

などがあるようです。

1)は、最も安全だそうですですが、アプリケーションのバージョンアップ等で変更を忘れてしまいそうです。また、アプリケーションによっては使えません。2)は、今までログイン時(個別ユーザ用)に設定していたものを、他ユーザにも影響がでるような形で設定するのは、若干抵抗があります。設定自体は、シェルスクリプトの記法に近く楽そうでよいのですね。
3)は、設定がアプリケーション単位で個別にできるのがよい点です。記述は若干面倒そうです。(使い方はLaunchDaemons (launchctl, launchd.plist) の使い方にわかりやすくとめられていました)

いろいろ考えた末、以下の方針にしました。方針というほど大げさなものでもないのですが。
  1. /etc/launchd.confを使用するが、設定は最小限にする。特に、セキュリティのため、自分のIDの書き込み権がある場所は指定しない。
  2. 個別のアプリケーション内の環境設定等で対応できるものは、そこで対応する。NerdToolのシェルスクリプト等、手間がかからないものも各スクリプトで設定する。
  3. 1.〜2.で対応できない場合、そのアプリケーション用のlaunchd.plistを作成し、ユーザ領域の~/Library/LaunchAgents で管理する
  4. アプリケーション内のInfo.plistを修正は、バージョンアップ時に修正を忘れたり管理が大変なため行わない。

/etc/launchd.confを設定する前に、現在のlaunchdのPATH設定を調べたところ、以下のようになっていました。
$ sudo launchctl getenv PATH
/usr/bin:/bin:/usr/sbin:/sbin

/etc/launchd.confは存在していないのでこれらは、デフォルトで設定されているのでしょう。また、/etc/pathsは以下のようになっています。

/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin

自分のPATH設定に入っている$HOME/bin, /opt/local/bin, /opt/X11/bin, /usr/local/clamXav/binが含まれていませんが、これらはログイン後シェルで使うものが多いので/usr/local/binだけを設定することにしました。それ以外は、.bash_profile等で変更します。

/etc/launchd.confには、

setenv PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

と設定しました。また、/etc/pathsもそれに合わせて/usr/local/binを先頭に持ってきました。

また、crontabやNerdToolなどのシェルは、必要に応じてPATHを追加する方針ですが、現状既にそのように修正しているので基本的にはそのままです。PATHの追加が必要になるのは、ほとんどの場合、$HOME/bin か /opt/local/bin (MacPorts用のパス) です。

感想

environment.plistがサポートされなくなった背景には、Flashbackマルウェアの発生などMac OS Xでもセキュリティを厳しくする必要があるということが挙げられます。Mountain Lionでのsandbox化や承認されたアプリケーションしか基本的にはインストール・起動できないというのもその流れですね。もっと自由にしたいとか、いろいろ意見もあるようですが、今後ますますユーザレベルでも気を付けなければならないのではと思います。

[追記 2013/1/16 ] http://jvn.jp/cert/JVNTA13-010A/ によると、JAVAにまたセキュリティホールが見つかっていますね。注意したいものです。

2012年10月7日日曜日

growlnotifyをiCalのアラーム代わりに使ってみる

iCalにイベントを登録して、時間が来たら知らせてくれるようにアラームを設定しています。朝など忘れやすいので、結構便利に使っています。

ただ、毎日決まった時間にやらないといけないことをiCalに繰り返しイベントとして登録していると、iCalの画面が同じイベントで溢れて、その他のイベントが見づらくなってしまいます。下の図はそれほどでもないですが。

iCalのカレンダーの種別を追加して、「定期的(隠す)」ためのイベント用を登録して普段は表示しない設定にすれば、隠すこともできますが、別の方法はないか考えてみました。

イベントの通知といえばGrowlですがそれに含まれているgrowlnotifyを使うとスクリプトベースで画面に通知を表示できそうです。環境はSnow LeopardとGrowl 1.2.2で試してみました。
全体の流れは、(1) growlnotifyのインストール、(2) 表示用スクリプト作成、(3) crontabへの設定となります。

(1) Growlのインストールだけでは、growlnotiryはインストールされませんので、Growlのインストールの後に、growlnotiryをインストールします。Growlのインストール用ディスクイメージをマウントすると、Extraフォルダの下にgrowlnotify.pkgというインストールパッケージがあります。
そのパッケージをインストールすると、/usr/local/bin/growlnotifyに実行ファイルがコピーされます。(Suspicious Package qlgeneratorより)
grwolnotifyのmanページもインストールされるので、それを見ると使い方は大体わかります。

(2) manページなどを参考にスクリプトを作成します。以下に例を示します。(ブログ用にちょっと簡略化していますが)

#!/bin/sh
/bin/date "+今日の%H:%M%n金魚にえさ" | /usr/local/bin/growlnotify -s -a iCal -d feed crontab

このスクリプトに、kingyo.shのような名前をつけて実行権限を付けて( chmod +x) おきます。
このスクリプトを実行すると、次のように表示されます。
growlnotiryの-sオプションは、表示がタイムアウトしないようにします。左上に現れるクローズボックスで表示を消せます。

-aオプションは、アプリケーションアイコンを指定します。iCalを指定したらiCalのアイコンが表示されます。なくてもかまいませんし、他のアプリケーションを指定することもできます。
-dオプションは、現在発行しようとしている通知にIDを付けるものです。既に同じIDのGrowlのウィンドウが開いていると、新たにウィンドウを開かずに、既に開いているウィンドウの内容が上書きされます。
最後の引数のcrontabは、ウィンドウの一行目に表示されるタイトルです。自分はcrontabで表示させるのでこうしましたが、これもiCalや他の好きなタイトルにすればいいと思います。
また、dateコマンドの+オプションで日付を含むメッセージを表示できます。それぞれ、%Hが24時間表示の時間、%Mが分、%nが改行を示します。

(3) 上で作ったgrowlnotify用スクリプトがちゃんと表示されるのが確認できたら、crontabに登録して定期的に実行できるようにします。最近の流儀に合わせてlaunchdで自動起動を指定してもいいと思います。(ここではcrontabを説明します)
crontabの現在の登録内容を確認するためのコマンドは、
$ crontab -l
です。出力内容をリダイレクトしてバックアップをとっておくといいでしょう。
crontabでデータベースを直接編集する場合のコマンドは
$ crontab -e
です。vimではなく、nanoやemacsを使う場合、環境変数EDITORにそのコマンドを設定してください。emacsを使いたい場合は以下のとおりです。

$ export EDITOR=emacs

朝7時30分に実行する場合は、以下のようになります。
30 7 * * * $HOME/bin/kingyo.sh
既に他の定義がしてある場合は、最後の行にでも追加するといいと思います。
crontabのデータベースのフォーマットは、タブコード区切りで、順番に分、時間、日、月、曜日(0が日曜日)、コマンドとなっています。
現在の時間に近い時間を設定してテストするといいと思います。

以上ですが、実はiCalにも通知の頻度は落としていますが(毎日ではなく、何日に一回とか)、同じイベントを記入したままにしています。
今のところ、スケジュール関係のデータベースはiCalをメインに考えていますので、データとして残しておきたいため、そのようにしています。