
弊社では私を含め、退勤時もPC電源は落とさず、ディスプレイの電源のみを落とす人がほとんどです。ネットワークモニタ用に使っている岡持ち MacPro (Mid 2010) もそうしたいのですが、繋いでいるディスプレイに電源ボタンが無いため、 ディスプレイ スリープ を スケジュール 管理 することで、消し忘れ退勤防止に貢献してみます。
電源ボタンの無い LED Cinema Display (27-inch)
このMac Pro(OSは 10.13 High Sierra)に使っているのは、27inch LED Cinema Display、そしてもう一枚繋いでいるのは、以前取り上げたツイ廃液晶で、これらいずれにも電源ボタンは有りません。
退社時にPCの電源は落とさずにディスプレイの電源を落とすのが通例ですが、在籍中はネットワークモニタという性格上、ディスプレイスリープを無効にしています。そこで、出社時間・退社時間に合わせ、ディスプレイスリープの設定を自動的に変えたい、と言うのが本記事の命題です。
CLIでディスプレイのオン・オフ
ディスプレイ即スリープ
システム環境設定(System Preferences)内の省エネルギー(Energy Saver)項にある設定項目を、コマンドラインで行えるのがpmsetで、設定を変更するような命令にはroot権限が必要になりますが、オンデマンドで即ディスプレイスリープにするだけならば、以下のコマンドを実行するだけでroot権限も不要です。
1 |
$ pmset displaysleepnow |
ディスプレイ状態の検出
現在のディスプレイの状態も pmset で確認することが出来るので、sshでのリモート操作やスクリプト処理に利用できます。
1 2 3 4 5 6 7 8 9 |
$ pmset -g powerstate IODisplayWrangler Driver ID Current State Max State Current State Description IODisplayWrangler 4 4 USEABLE <--ディスプレイオン $ pmset displaysleepnow $ pmset -g powerstate IODisplayWrangler Driver ID Current State Max State Current State Description IODisplayWrangler 1 4 None <--ディスプレイオフ |
ディスプレイスリープタイマ無効
ここからはスリープタイマの設定を触るので、root権限が必要です。まず勤務時間中のスリープ無効は、 displaysleep の値を0にします。
1 |
# pmset -a displaysleep 0 |
pmset -g custom でも、現在の設定内容を確認することが出来ます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ pmset -g custom AC Power: hibernatemode 0 womp 1 networkoversleep 0 sleep 0 Sleep On Power Button 1 ttyskeepawake 1 hibernatefile /var/vm/sleepimage autorestart 0 disksleep 10 displaysleep 1 $ sudo pmset -a displaysleep 0 && caffeinate -u -t 1 $ pmset -g custom | grep displaysleep displaysleep 0 |
ディスプレイスリープタイマ有効
対して勤務時間外は最速でディスプレイスリープして欲しいので、 displaysleep を有効な最小値 1 (分)と設定します。
1 |
# pmset -a displaysleep 1 |
これもコマンドラインで確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ pmset -g custom AC Power: hibernatemode 0 womp 1 networkoversleep 0 sleep 0 Sleep On Power Button 1 ttyskeepawake 1 hibernatefile /var/vm/sleepimage autorestart 0 disksleep 10 displaysleep 0 $ sudo pmset -a displaysleep 1 $ pmset -g custom | grep displaysleep displaysleep 1 |
ウェイクコマンド
ディスプレイスリープを有効にしていて、スリープしているディスプレイは、ディスプレイスリープを無効にしただけではスリープから復帰しないので、別途ウェイク処理が必要です(root権限は不要)。
1 |
$ caffeinate -u -t 1 |
尚、システム環境設定内の省エネルギー項でも、スケジュール設定することも可能です。
スリープタイマが効かないとき
ディスプレイスリープタイマを設定したのに、時間になってもスリープに落ちないことがあります。原因はさまざまですが、その中で少し珍しいのが、こちらのフォーラムの回答の一つに挙がっていた、
「オフラインプリンタに未完のジョブがいないか」
と言うものでしょう。実際、既にリプレースしてネットワークからいなくなったプリンタが、まだ設定内に残っていたので消しました。
それでも思惑通りにディスプレイスリープに入ってくれない場合は、 pmset で現在のステータスを取得して確認します。以下の例では、 MAGICWAKE が怪しい箇所ですね。尚、この時、ssh越しにコマンド実行・取得しているので、 NetworkClientActive 項が 1 になっていますが、ssh接続によりスリープが妨げられることはありません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ pmset -g assertions 2021-08-20 11:20:07 +0800 Assertion status system-wide: BackgroundTask 0 ApplePushServiceTask 0 UserIsActive 1 PreventUserIdleDisplaySleep 0 PreventSystemSleep 0 ExternalMedia 0 PreventUserIdleSystemSleep 0 NetworkClientActive 1 Listed by owning process: pid 98(hidd): [0x0000001000098039] 00:00:03 UserIsActive named: "com.apple.iohideventsystem.queue.tickle.4294968311.17" Timeout will fire in 56 secs Action=TimeoutActionRelease pid 56(powerd): [0x000000c0001181de] 00:10:04 NetworkClientActive named: "com.apple.powermanagement.ttyassertion" Kernel Assertions: 0x104=USB,MAGICWAKE id=500 level=255 0x4=USB mod=1/1/1970, 8:00 AM description=com.apple.usb.externaldevice.fd300000 owner=IOUSBHostDevice id=503 level=255 0x4=USB mod=1/1/1970, 8:00 AM description=com.apple.usb.externaldevice.fd330000 owner=Keyboard Hub id=505 level=255 0x4=USB mod=1/1/1970, 8:00 AM description=com.apple.usb.externaldevice.fd331000 owner=Apple Optical USB Mouse id=506 level=255 0x100=MAGICWAKE mod=1/1/1970, 8:00 AM description=en1 owner=en1 Idle sleep preventers: IODisplayWrangler |
この時は、普段使わないマウス・キーボードを繋いだままデスク端に片付けていたのですが、その際のマウスが微妙に接地しておらず、動作誤認識がスリープを妨げていました。
macOSのcron
本来、macOSにおいてcronは非推奨であり、launchdを使うのが推奨とされていますが、今回は勝手知ったるcronで本命題を実現させたいと思います。非推奨になっても実はlaunchdによってcronは管理されていて、そのplistファイルは次のようになっています。
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 |
$ sudo cat /System/Library/LaunchDaemons/com.vix.cron.plist <?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>com.vix.cron</string> <key>ProgramArguments</key> <array> <string>/usr/sbin/cron</string> </array> <key>KeepAlive</key> <dict> <key>PathState</key> <dict> <key>/etc/crontab</key> <true/> </dict> </dict> <key>QueueDirectories</key> <array> <string>/usr/lib/cron/tabs</string> </array> <key>EnableTransactions</key> <true/> </dict> </plist> |
そして今回実現させたい処理を時系列的に図示したものが次のようになり、これを平日に適用します。
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 |
------------------------------- + | | DISPLAY | SLEEP | ------------------------------- 7:51am nosleep & wake ------------------------------- | # pmset -a displaysleep 0 | # caffeinate -u -t 1 | | NO | DISPLAY | SLEEP | ------------------------------- 5:00pm 1min sleep ------------------------------- | # pmset -a displaysleep 1 | | DISPLAY | SLEEP | + ------------------------------- |
これを crontab -e で以下のように記述します。
1 2 3 |
# Change Display Sleep Policy 51 07 * * 1-5 /usr/bin/pmset -a displaysleep 0 && caffeinate -u -t 1 00 17 * * 1-5 /usr/bin/pmset -a displaysleep 1 |
何もジョブが設定されていない時、cronプロセスは起動していませんが、ジョブを追加することで自動的にプロセスも動き始めます。
1 2 3 4 5 6 7 |
$ sudo crontab -e crontab: no crontab for root - using an empty one crontab: installing new crontab $ ps -ax | grep cron 1652 ?? 0:00.01 /usr/sbin/cron 1655 ttys001 0:00.00 grep cron |
これで命題を達成し、勤務時間中はディスプレイスリープ無効、同時間外は1分スリープになりました。祝日の日中については割愛、長期休暇時はそもそもPCシャットダウンさせるので問題無いでしょう。