ジンジャー研究室

長めのつぶやき。難しいことは書きません。

時間帯によって特定サイトの閲覧を禁止する for macOS

f:id:jinjor:20181024032631p:plain

TL; DR

cron で /etc/hosts を書き換える。

* 6-22   * * * /usr/bin/sed -i '.bak' -E 's/(.*)#block$/#&/g' /etc/hosts
* 0-5,23 * * * /usr/bin/sed -i '.bak' -E 's/^#+(.*)#block$/\1#block/g' /etc/hosts

以下、この方法に到るまでの経緯。

動機

SNS が時間泥棒だからアクセス出来ないようにしたい、というのは昔から言われているのだが、特にまずいのは Slack だと思っている。Twitter は流しておけばいいんだけど Slack はチャットなので会話が発生する。見るだけなら問題ないじゃんと思いつつ、見るとつい返信したくなる。そういう人が2人以上いると無限ループになり深夜に突入。で、他の人が朝に見たらなんか会話が進んでいる状態。よくない。

なんとか Slack を使うのを止める方法はないのか?

対策を考える

で、色々と検討したのをメモ。前提条件としては macOS

bot に怒ってもらう

Slack だから、深夜時間帯に使ったら個人宛に怒ってくれる bot とかがいれば、書き込みを抑止できるのではないか。

結論としては、睡眠モードに通知を出さない機能はあるが bot は無さそう 。 作ることは出来そうだが面倒。(調べてないけど個人単位で bot の導入できるんだっけ?全員にルールを適用されるのは嫌だ。それやったら朝に強制ラジオ体操やるのと変わらない。)

ペアレンタルコントロール

子供が深夜などにアプリを使用するを制限する機能のようだ。なるほど、大人の皮を被った子供は潔く子供扱いされねばなるまい。 ただし、管理者は子供になれないので子供用のアカウントを作らないといけない。大人のアカウントで設定して子供の方にログイン…うーん面倒。

SelfControl

SelfControl という自制心の効かない大人のためのアプリがある。ブラックリストに入れたサイトに一定時間アクセス出来なくなるらしいのだが、そのボタンは自分で押さなければならないようだ。いや、そんなに意志は強くない。

Airplane Mode

Airplane Mode という同じく自制心の効かない大人のためのアプリがある。てか、 Evan さん何やってんすか。デスクトップにアイコンを置いて、叩くと /etc/hosts を書き換える Python スクリプトが走る。ただこれも手動で叩かないといけないのがな〜という気分。

cron で /etc/hosts を書き換える

ズバリというものがなかったので、/etc/hosts を書き換えるというアイデアだけ拝借する。 ブロックしたいサイトに #block のような印をつけておいて、指定した時間になったらその行を sed でコメントイン・アウトすればいい。

0 06 * * * /usr/bin/sed -i '.bak' -E 's/(.*)#block$/#&/g' /etc/hosts
0 23 * * * /usr/bin/sed -i '.bak' -E 's/^#+(.*)#block$/\1#block/g' /etc/hosts

正規表現には自信がないが、以下がコメントアウトされるはず。

...

0.0.0.0 xxx.slack.com #block
::      xxx.slack.com #block

これで OK 、のはずだった。

DNS の反映が遅い

しかし DNS の反映が遅い。

ということでググると、 DNS キャッシュをクリアする方法が OS 毎に出てくる。で、色々試して最後に残ったのが ChromeDNS キャッシュで、chrome://net-internals/ にアクセスしてボタンを押すしか方法がなく、コマンドで消せない。 「じゃあ puppeteer でボタンを押そうか」という事で調べたら、すでに同じことを試みた人が出来ないと言っていて、さらにたどると chromium のフォーラムで「headless モードで chrome://net-internals/ にはアクセス出来ないよ」という回答が付いていたので、意図的っぽい。

というわけで DNS の反映は諦めた。まあ 30 分くらい早めにすれば多少のずれは良しとしよう。

スリープ中に cron が走らない

23時にセットしたから今頃見えなくなっているはずで、と思って Slack にアクセスしたら超見え見えじゃん〜。cron の設定は正しいっぽく見えるので、やはり mac がスリープ状態だと無理なのか。

調べると mac を不眠に陥れようという酷い方法が提案されていて、心が痛んだのでやめておいた。 さらに調べると、sleepwatcher というツールを使うと起動した時にスクリプトを流すことができるらしい。が、情報少ないし信頼性もわからなかったのでやめておいた。

毎分実行する

そして、最終的に「起きてる間に毎分走らせりゃいいか」ということになった。

* 6-22   * * * /usr/bin/sed -i '.bak' -E 's/(.*)#block$/#&/g' /etc/hosts
* 0-5,23 * * * /usr/bin/sed -i '.bak' -E 's/^#+(.*)#block$/\1#block/g' /etc/hosts

ちゃんと動いていそう!

まとめ

もっと良い方法があれば教えてください。