过去N年都上推太多,过去一年总想限制自己上twitter的时间,让工作效率提高起来,但时常看着 rescuetime.com/dashboard 的 social network 类别当日使用时长超过一小时(我给自己定的上推时长阈值),依然停不下看推发推的步伐。。。 最近借着内部和外部多种因素,写了个限制发推时段的脚本,现在把方法和经历总结一下。

要做的是: 限制在制定的时段内,twitter.com不能在电脑上访问,无论客户端还是browser。系统环境是Mac OS X 10.7,随便想了几种方案,决定用crontab加bash script修改/etc/hosts文件中twitter的api/stream/search地址来完成操作。

首先,/etc/hosts 文件中添加如下三行

127.0.0.1 api.twitter.com
127.0.0.1 search.twitter.com
127.0.0.1 stream.twitter.com


这时候twitter就无法访问了。然后写一个bash脚本,根据当前时间,确定在上面的几行内容最前部前添加或者去除注释符号来完成启用或者禁用封锁twitter的功能。脚本blocktwitter.sh内容如下

#!/bin/bash
HOUR=`date "+%H"`
BLOCK=0
if [ "$HOUR" -ge 9 -a "$HOUR" -lt 12 ]; then
  BLOCK=1
fi
if [ "$HOUR" -ge 13 -a "$HOUR" -lt 18 ]; then
  BLOCK=1
fi
if [ "$BLOCK" -eq 1 ]; then
  #echo "block twitter"
  sudo sed -i -e \
  "s/^#127.0.0.1 \(.*\).twitter.com/127.0.0.1 \1.twitter.com/g" \
  /etc/hosts
  say "Now blocking twitter"
else
  #echo "unblock twitter"
  sudo sed -i -e \
  "s/^127.0.0.1 \(.*\).twitter.com/#127.0.0.1 \1.twitter.com/g" \
  /etc/hosts
  say "Now unblocking twitter"
fi


  • 以上使用sed程序的替换命令对 /etc/hosts 文件做操作。
  • "$HOUR" -ge 13 -a "$HOUR" -lt 18表示如果时钟小时数大于等于13并且小于18,这个可以根据需要进行调节(脚本中的时间是我司上班时段:)
  • sed命令为了在此theme中不显示太长造成难看的状况,我用\将其折成了3行了,没有实地测试是否这个折行是没有问题的

最后,使用

sudo crontab -e


命令编辑root用户的定时任务。在编辑器中添加

0 * * * *    /bin/bash /Users/username/shell/blocktwitter.sh


行尾一定要有换行/回车。表示每小时的第0分钟执行/Users/username/shell/blocktwitter.sh脚本。这样,每小时检查并根据策略执行一次启用或者禁用twitter域名封锁的禁推脚本就完成了。

注意:最初不知道为何我试验crontab的时候总是执行不到脚本内容;后来经过不知是偶然还是必然的一次修改尝试,我把最后一个定时条件/最后一个星号(*)和执行命令(/bin/bash)之间的空格换成了TAB(制表符/0x09)就一切OK了,后来因为时间所限(其实是懒!)没有查证了,有空和好奇心的童鞋可以探究一下,可以告诉我下结论。还有就是crontab可以(有些是必须)添加SHELL/PATH/MAILTO环境变量,否则有些脚本中的功能会执行不了。

本文中还是有一些说得不够细致,也还有功能不足之处,不过这些细节和补充都是可以google到的,我也是一边google一边写完了这个脚本,不带debug奇怪问题的话也就半个小时就完成了这个功能,大家有什么更多需要更好的主意,尽情地自己扩展吧:)

我推特 https://twitter.com/kcome :)

从这次开始,把一些技术技巧记录也写在blog里,否则对我这种写博拖延症来说,保持一定频率真太难了。。。拖延症其实都是coding或者干活强迫症造成的,干活强迫症有点让我其他什么都进行困难了。。。废话少说,正题开始,这是一个条件略有复杂和奇特的case,需求可能有些和别人的不同,之前没有搜到特别完美的方案,就把自己的脚本以及折腾过程记录下来。

需求/条件约束

  • 一台Mac OS X(当前是10.7.0)通过PPTP连接到另一端的远程网络(比如从家连接到公司)
  • 远程网络通过ADSL拨号连接互联网,没有动态DNS,但是有某静态IP的web页面公布其地址
  • Mac OS X连接了两个内网(有线和无线),分别为192.168.1.0和192.168.2.0,远程网络的内网是192.168.0.0

连接过程

全程仅用Autormator里添加一个“Run AppleScript”任务,任务中有不少“do shell script xxx”的语句调用命令行工具。代码如下

on run {input, parameters}
  set REMOTEIP to do shell script ¬
  "curl -s http://11.22.33.44:8080/showip | grep -Eo \"([[:digit:]\\.]+)\""
  do shell script "sed -i -e \"s/.* remoteIP.local/" & REMOTEIP & ¬
  " remoteIP.local/g\" /etc/hosts" with administrator privileges
  do shell script "dscacheutil -flushcache"
  do shell script "route -n add -static " & REMOTEIP & ¬
  " 192.168.2.1" with administrator privileges
  tell application "System Events"
    tell current location of network preferences
      set VPNservice to service "VPN NAME IN SYSTEM PREFERENCES"
      if current configuration of VPNservice is not connected then
        connect VPNservice
        repeat while current configuration of VPNservice is not connected
          delay 1
        end repeat
      end if
    end tell
  end tell
  do shell script "route -nv add -net 192.168.0.0/24 10.0.0.2" ¬
  with administrator privileges
  return input
end run

其中“¬”是OPTION+ENTER/RETURN,只是将太长的单行语句折行方便显示用的。

注记

curl -s http://11.22.33.44:8080/showip | grep -Eo "([[:digit:]\\.]+)"

因为暴露远程网络IP地址的静态页面显示的并非一个单独的IP地址,这里用grep把其他无用信息过滤掉,将被扒光的IP地址付给变量REMOTEIP

do shell script "sed -i -e \"s/.* remoteIP.local/" & REMOTEIP & ¬
" remoteIP.local/g\" /etc/hosts" with administrator privileges

我再解释一下上面这行。因为远程网络的IP地址不固定,而Mac OS X里PPTP VPN的目标IP地址目前没有找到好方法用命令行或AppleScript修改,所以这里采用的方法是填写一个本地主机名“remoteIP.local”,然后在 /etc/hosts 文件中写入 “11.22.33.44 remoteIP.local”,这样就避免了在AppleScript或命令行下修改VPN连接目标IP的需求。这个方法虽然有点迂回和龌龊,但是其他更便捷的方法还没发现。缺点还包括每次连接vpn都要修改hosts文件,洁癖表示接受起来鸭梨略大。

route命令是让VPN连接走指定网关的。我是一开机即连上美国VPN的并设置为全局路由,而这里又希望连接办公网络的PPTP VPN不经过美国VPN,就指定了直接从网关经过。

下面的VPN连接代码应该是很容易可以google到的,到处都有解释这里就不多说了。

注意一点是如果命令行操作需要sudo,只需要去掉它并在do shell script “bla bla bla”后加“with administrator privileges”即可。虽然简单的东西也找了挺久,不知道是我不会找还是AppleScript文档比较囧。

其他就没什么了把。先到这里吧:)