[Mac] スリープ復帰時に NAS を再接続する方法
我が家の NAS
我が家は、BUFFALO の LinkStation LS-QL という NAS を使っています。こんなキューブ状の NAS で 3.5インチの HDD が4台入ります。
2008年当時、安価に RAID 5 が組めたので飛びついて今も使い続けています。この NAS には自動省電力機能が付いていて、接続しているパソコンがいなくなると自動的に電源を切って省電力モードに入ります。我が家の iMac は作業を終えるとスリープにしているのですが、スリープでももちろん NAS の電源が切れます。スリープから復帰すると、Mac に入っている NAS ナビゲーターが NAS に信号を送って NAS が自動的に起動を開始します。起動して使えるようになるまでに数分かかります。
解決したい課題
- スリープから復帰したときに自動的に NAS を再マウントしたい
- NAS が省電力モードから復帰した場合でも確実にマウントしたい
- ファイルアクセスが突然おかしくなる問題(後述)を回避したい
いたってシンプル。単にスリープから復帰したときにも自動的にまた NAS がマウントされていて欲しいということです。ただ、NAS が省電力モードに入っている時(たいてい入っている)は NAS 起動に数分間かかるので起動を終えたらなるべくすみやかに自動マウントして欲しい。
単純なことなのでググればたくさん出てきそうなのですが、世の中のみなさん NAS は起動しっぱなしが前提なようで我が家と同じケースで悩まれていて解決した例を見つけることができませんでした。
解決方法
AppleScript を使った解
考え方としては、定期的にマウント状態をチェックしてマウントされていなかったらマウントコマンドを発行するというものです。調べながら書いてみたスクリプトは次のもの。AppleScript エディタで編集しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
property bFirst : true property interval : 5 * minutes on idle if bFirst is true then set bFirst to false log "it is the first time, so skip the process." return interval end if log "check the mounted volumes..." tell application "Finder" if not (exists disk "private") then log "Mounting [private] volume..." activate mount volume "afp://LINKSTATION._afpovertcp._tcp.local/private" end if if not (exists disk "share") then log "Mounting [share] volume..." activate mount volume "afp://LINKSTATION._afpovertcp._tcp.local/share" end if end tell log "back to idle state." return interval end idle |
2行目:監視インターバルをセットしています。NAS の起動時間を鑑みて5分にしています。
4行目:on idle を利用して、定期的な監視を行うハンドラ部分を記述しています。
5〜9行目 : スリープ復帰直後はどうせ NAS がまだ起動していないのでなにもせずスキップしています
12行目:Finder に対してコマンドを送るよ宣言
13行目 : exists disk “private” で private という名前のデイスクがあるかどうかを判定します。private は我が家の NAS のボリューム名なので、環境に合わせて変更が必要です。
15行目 : Finder が起動していなかった場合に起動します(起動していないと命令を送れない)
16行目 :private ボリュームを /Volumes/private にマウントします
※アクセス認証をかけている場合には次のようにします
mount volume “afp://LINKSTATION._afpovertcp._tcp.local/private” as user name “user” with password “pswd”
“user” と “pswd” を実際の設定に変更します。
19行目以降も同様に “share” ボリュームに対して 操作を行います
このスクリプトをアプリケーションの形式で書きだします。
ファイルフォーマットを「アプリケーション」、「ハンドラの実行後に終了しない」にチェックを入れておきます。さもないと起動と同時に何もせずに実行を終了してしまいます。起動しっぱなしにすることで on idle ハンドラが呼び出されます。
ここでは、automount.app として書きだしました。あとは「システム環境設定」- 「ユーザとグループ」- 「ログイン項目」に automount.app を設定してあげれば Mac 起動時に自動的にスクリプトが走り始めます。
このスクリプトによってとても快適になったのですがある日問題に気づきます。それが解決したい課題の3番目に書いた「ファイルアクセスが突然おかしくなる問題」です。それが顕著に出るのが iTunes を開きっぱなしでスリープした後の復帰です。我が家では iTunes のライブラリそのものをすべて NAS に置いてあるのですが、復帰後に音楽を再生するとなんと別な曲がかかることがあるのです。
楽曲を右クリックして「ファインダーに表示」を選ぶと確かに別な曲が入っているフォルダが開いてしまいます。さらに、そのフォルダから上位階層をたどろうとすると、まったく別なフォルダに飛んだり自分自身に戻ってきたりととても不可解な挙動をしめします。この症状を直すためには、一度ボリュームをアンマウントしてから再度マウントし直す必要があります。
結局原因は定かではないですが、何度かこのような症状に遭遇したため別な方法をとることにしました。
SleepWatcher を使った解
解決したい課題 3 の不可解な症状が出ないようにするには、スリープ時に NAS のボリュームをすべてアンマウントしてきちんといなくなる処理が走ればよいのではないかと考えました。アプリから見ると復帰したら突然 NAS がいなくなっているというのがいかんのではないかと。
色々調べていたら、sleep watcher というよさげなツールを見つけました。Mac がスリープに入るときとスリープから復帰した時を監視していて好きなコマンドを起動できるというスグレモノです。結論から言うと、このツールを利用することですべての問題がなくなりました!
以下導入方法です。
1.SleepWatcher ダウンロード
ダウンロードページよりダウンロードします。味も素っ気もないページで、どこからダウンロードするのか分かりにくいですが真ん中編に「SleepWatcher 2.2」というリンクがあります。それをクリックするといきなり圧縮されたファイルがダウンロードされます。
解凍して ReadMe.rtf を開くと説明が書いてあるのですがこれもまた味も素っ気もないドキュメントで分かりにくいかもしれません。順を追って説明します。以下はデスクトップに解凍した場合の説明です。別な場所に解凍した場合には「~/Desktop」を置き換えてください。
2.実行ファイルと man ファイルをコピー
1 2 3 |
$ sudo mkdir -p /usr/local/sbin /usr/local/share/man/man8 $ sudo cp ~/Desktop/sleepwatcher_2.2/sleepwatcher /usr/local/sbin $ sudo cp ~/Desktop/sleepwatcher_2.2/sleepwatcher.8 /usr/local/share/man/man8 |
3.シェルスクリプトを用意
スリープ時と復帰時のシェルスクリプトを用意します。まずは、スリープ時。マウント中の NAS を明示的にアンマウントします。
1 2 |
diskutil unmount force /Volumes/private diskutil unmount force /Volumes/share |
umount コマンドではうまくアンマウントできないことがあるため diskutil を使用しています。 このスクリプトを before_sleep という名前で保存し、
chmod u+x before_sleep
として実行属性をつけておきます。
次に、復帰時。
1 2 3 4 5 |
sleep 240 mkdir /Volumes/private mount_afp afp://LINKSTATION._afpovertcp._tcp.local/private /Volumes/private mkdir /Volumes/share mount_afp afp://LINKSTATION._afpovertcp._tcp.local/share /Volumes/share |
最初の行の sleep 240 は 240秒間待ってからマウントするために入れてあります。省電力モードからの NAS の再起動に数分かかるからです。
NAS が起動して十分時間が経った頃に、mount_afp コマンドで NAS のボリュームをマウントします。このスクリプトを after_awake という名前で保存し、
chmod u+x after_awake
として実行属性をつけておきます。
4.launchd 用のコンフィグファイルを作成する
下記のようなコンフィグファイルを用意します。SleepWatcher の config フォルダに入っているサンプルを利用しました。11行目と12行目だけ書き換えればよいでしょう。先ほどの before_sleep と after_awake スクリプトのパスを設定しています。ファイル名はそのまま de.bernhard-baehr.sleepwatcher-20compatibility-localuser.plist で保存します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>de.bernhard-baehr.sleepwatcher</string> <key>ProgramArguments</key> <array> <string>/usr/local/sbin/sleepwatcher</string> <string>-V</string> <string>-s /Users/[ユーザ名]/Documents/scripts/sleepwatcher/before_sleep</string> <string>-w /Users/[ユーザ名]/Documents/scripts/sleepwatcher/after_awake</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> </dict> </plist> |
5.launchd への登録
まず、上記の plist ファイルをコピーします。
1 |
cp de.bernhard-baehr.sleepwatcher-20compatibility-localuser.plist ~/Library/LaunchAgents |
次に launchctl を使用して launchd に登録します。
1 |
launchctl load de.bernhard-baehr.sleepwatcher-20compatibility-localuser.plist |
無事に登録されたことを確認するには、
1 |
launchctl list | grep sleep |
として、
1 |
nnn - de.bernhard-baehr.sleepwatcher |
上記の表示が出れば OK です。整数値 nnn は環境によって異なります。
これで、Mac 起動時に launchd によって自動的に SleepWatcher が起動し、以降はスリープと復帰を監視して自動的に設定したシェルスクリプトを実行してくれます。めでたしめでたし。
アンマウントに多少時間がかかるためか、スリープまでに少し時間がかかるようになってしまいましたがあまり気になりません。
電気代や節約精神を考えずに NAS を常時起動しておくのが最良の解かもしれませんが、僕と同じような貧乏性の方は常時起動が気になることでしょう。そういう方の参考になれば幸いです。