在Mac上通过Terminal截取网页全图 / Full Page Screenshots by Terminal On a Mac

在Mac上通过Terminal截取网页全图 / Full Page Screenshots by Terminal On a Mac

其实很多人都知道,如果说Snow Leopard和Windows 7的图形界面是可口的点心的话,那么在*nix系统里面,命令行Shell简直就是系统的灵魂。 笔者是从事网站开发和设计的,俗称的D&D(Design and Development),经常遇到需要把制作效果汇报给上级,或者发Demo给客户的情况。然而由于Web pages脱离了Web server通常是无法完整预览的,这就需要截图了。 Mac上截图是很方便的,系统自带的截图功能就异常强大(和Windows上残废的截图功能无法类比),而且通过便利的热键就能使用。关键是Mac上的截图工具并不能截取网页的全图,也就是遇到你的网页尺寸大于你的浏览器窗口尺寸的时候,就无能为力了,难不成还要开个Photoshop来拼接?这样做很山寨,一点都不专业,而且效率相当低。于是我也尝试过使用Paparazzi和Little Snapper。说实话,这两个软件都是很优秀的,特别是华丽的Little Snapper,但是那就需要多安装一个软件了,有没有什么环保一点的办法呢? 经过一番研究,其实是有的,就是使用基于python的webkit2png,然而事实上Paparazzi和Little Snapper都是基于webkit2png项目的。 webkit2png可以在这里下载到:http://www.paulhammond.org/webkit2png/ 如果你和我一样,有命令行癖,那么打开Terminal,使用CURL获取,命令如下: curl http://www.paulhammond.org/2009/03/webkit2png-0.5/webkit2png-0.5.txt > webkit2png 于是你就得到webkit2png了。怎么用呢? 首先检查你的系统,你必须使用Mac OS X 10.2或以上系统,Safari 1.0或以上,PyObjC库1.1或以上。当然了,如果你的系统是Mac OS X 10.5 Leopard或更高版本,那么以上所有组件,你都已经安装过上了。如果不满足条件,可以升级Safari,并下载PyObjC的源代码自己编译。 webkit2png的使用很简单,Terminal执行: python /Users/Leask/webkit2png https://leaskh.com/ 执行效果如下: 然后你就会发现网页已经被截图放在你的home文件夹了。 当然你还可以通过参数控制webkit2png的行为,你可以通过 –help 获得以下使用帮助: Flora:~ Leask$ python /Users/Leask/webkit2png –help Usage: webkit2png [options] [http://example.net/ …] examples: webkit2png http://google.com/ # screengrab google webkit2png -W 1000 -H 1000 http://google.com/ # bigger screengrab of google webkit2png -T http://google.com/ # just the thumbnail screengrab webkit2png -TF http://google.com/ # just thumbnail and fullsize grab webkit2png -o foo http://google.com/ # save images as “foo-thumb.png” etc webkit2png - # screengrab urls from stdin webkit2png -h | less # full documentation Options: –version show program’s version number and exit -h, –help show this help message and exit -W WIDTH, –width=WIDTH initial (and minimum) width of browser (default: 800) -H HEIGHT, –height=HEIGHT initial (and minimum) height of browser (default: 600) –clipwidth=WIDTH width of clipped thumbnail (default: 200) –clipheight=HEIGHT height of clipped thumbnail (default: 150) -s SCALE, –scale=SCALE scale factor for thumbnails (default: 0.25) -m, –md5 use md5 hash for filename (like del.icio.us) -o NAME, –filename=NAME save images as NAME-full.png,NAME-thumb.png etc -F, –fullsize only create fullsize screenshot -T, –thumb only create thumbnail sreenshot -C, –clipped only create clipped thumbnail screenshot -d, –datestamp include date in filename -D DIR, –dir=DIR directory to place images into –delay=DELAY delay between page load finishing and screenshot –noimages don’t load images 这里我就不一一翻译了。如果你懂一点Shell Script语言,还可以把这个命令再封装一下,例如我就把这个命令封装为: websnap [URL] 的形式,很便利地得到截图,如输入: websnap [https://leaskh.com](https://leaskh.com/)/ 至于Shell Script怎么写?也不难,Unix和Linux上的Shell Script其实都大致一样,如: #!/bin/bash echo “Leask’s WebSnap based on webkit2png” echo “” python /Users/Leask/webkit2png $1; exit; 保存上面的代码片段为以websnap为名文件,注意以上的Leask为我的用户名,你还需要自己改为自己的用户名呢。放脚本的目录和脚本本身都需要有执行权限。 就先写这些吧,Enjoy。 // 如果你是Linux用户,你通常没有Webkit,那么你有Firefox就可以了,Google一下另外一个基于Mozilla Firefox的项目叫做khtml2png,和webkit2png大同小异。

自己动手清理MacBook

自己动手清理MacBook

最近我的MacBook性能大不如前,稳定性下降,风扇噪音越来越大。 今天由于温度过高,突然断电,我可怜的写了一个多小时的数据分析告吹了,于是向公司反映,请假维修MacBook。 推测是散热风扇出毛病了,Google了MacBook的风扇价格,高得惊人,只能考虑自己修一下。 经高人(我哥)指点,找来一瓶“防锈润滑剂”,我选的叫做“WD-40”(现在买免费加送20%哦)。 其实一瓶也就10块钱,买一个原装风扇可以买几十瓶了。 大概这个样子的: 动手!开始拆开: 翻开上盖,尘封程度惨不忍睹,风扇基本上已经被灰尘堵住转不起来: 用废旧牙刷刷干净主板,使用润滑剂对着风扇轴承处,使劲喷。 注意,润滑剂使用二氧化碳推进,喷劲十足! 喷出来会是雾状,而且有腐蚀性,最好不要沾到手,而且最理想的情况是用纸巾把屏幕也遮蔽一下,大致情况如下: 来一张清洁前后的效果对比图: 然后按照拆开的方法装回去,机器立刻变得安静凉爽,如果你的是MacBook,并且使用时间达到一年左右,你应该会遇到和我一样的问题(网友大量反映),建议你试试我的方法。因为较低的温度会延长你风扇和内部零件的寿命。而且用起来,也不再烫手了。 // 最后提醒大家拆机有风险,要求胆大心细。祝你好运! // 对了,拆机的教程我是看ifixit的,一个很著名的Mac全系列拆解网站,里面的教程很详细,十分具有参考价值,网址请自行Google。

Flora_ssh-D Version 2.33 闪亮登场!

Flora_ssh-D Version 2.33 闪亮登场!

Flora_ssh-D是什么? Flora_ssh-D是一个Applescript(以app形式封装),在Mac OS上开发和运行(有计划推出针对Windows的版本); Flora_ssh-D是一个iTunes VoiveOver程序,能够像iPod shuffle那样自动报读当前正在播放的歌名和艺术家; Flora_ssh-D能够自动连接ssh -D服务器,自动创建Socks代理服务器,高速访问某些如Twitter、Facebook等国外优秀站点,并在连接断开的时候自动重连,配合ssh -D服务器使用,让Wall从此透明; Flora_ssh-D并不包含ssh -D服务器信息,如果你要使用第3条的功能,你需要自己购买ssh -D服务器,做有责任感的网民,网上行为务必符合国家法律法规; Flora_ssh-D能自动更新你的Twitter状态为你正在听的歌,如:【I am listening to #Sensible by #Sun Yan-Zi in album #Leave. // Thursday, October 29, 2009 11:05:32 AM】; Flora_ssh-D能自动记录你正在听的歌到Last.fm; Flora_ssh-D能自动更新你DNS-O-MATIC上的动态IP地址为你的当前IP; Flora_ssh-D能自动判断在线状态,自动为你开启和关闭某些软件; 推荐把Flora_ssh-D设置为开机启动,只需要在开机的时候执行这一个脚本,其他的程序可以配置到脚本里面,自动根据在线状态为你自动开启和关闭; Flora_ssh-D是开源的自由软件,并已经在Google Code上创建为开源项目:http://code.google.com/p/flora-ssh-d/ Version 2.33有什么新改进? 全新的任务调度,大大缩短iTunes VoiceOver的时间延迟; 全新的配置方式,现在下载程序后无需配置就能马上执行,比较适合只需要iTunes VoiceOver功能的朋友; 优化VoiceOver功能,添加音量淡入淡出功能,听起来效果更好,和iPod shuffle上基本上没有分别了; 完善Twitter功能,自动在Twitter上发布你正在听的歌; 完善last.fm歌曲记录功能; 修正ssh -D连接的bug,让ssh -D连接更加顺畅,并在退出程序的时候自动关闭ssh –D以释放内存; 进一步减少空闲时的资源占用,让脚本更轻巧,几乎感觉不到脚本的存在; 全新的任务管理方式,运行更快,更稳定; 添加中文配置说明,方便英文不好的朋友使用。 Flora_ssh-D 2.33 能够在以下地址下载到:http://code.google.com/p/flora-ssh-d/downloads/list 源代码如下: (* Flora_ssh-D Version 2.33 Open Source Project Home/开源项目主页: http://code.google.com/p/flora-ssh-d/ Code by/程序编写: 黄思夏 / Leask Huang Blog: https://leaskh.com (天朝访问需翻墙) E-mail/GTalk/MSN/QQ: i@leaskh.com *) (* CUSTOM THESE SETTINGS BEFORE YOUR RUN THINS SCRIPT // 运行此脚本前请先配置此区域的参数 LEAVE IT BLANK IF YOU DON’T NEED IT // 如你不需要其中某些功能请将设置留空 *) property SSHServerName : “” property SSHUserName : “” property SSHPasswd : “” property TwitterUsername : “” property TwitterPassword : “” property DNSUsername : “” property DNSPassword : “” property LastfmUsername : “” property LastfmPassword : “” property appStList : {} property appQuitList : {} (* Example/示例 // English Help // 中文帮助 property SSHServerName : “ssh.yourdomain.com” – ssh -D Server Address (or leave it blank) // ssh -D 翻墙服务器地址 (不使用ssh -D则留空) property SSHUserName : “**” – ssh -D User Name (or leave it blank) // ssh -D 帐号 (不使用ssh -D则留空) property SSHPasswd : “**” – ssh -D Password (or leave it blank) // ssh -D 密码 (不使用ssh -D则留空) property TwitterUsername : “**” – Twitter User Name (or leave it blank) // Twitter帐号 (不使用Twitter则留空) property TwitterPassword : “**” – Twitter Password (or leave it blank) // Twitter密码 (不使用Twitter则留空) property DNSUsername : “**” – DNS User Name (or leave it blank) // DNS-O-MATIC动态IP帐号 (不使用动态IP则留空) property DNSPassword : “**” – DNS Password (or leave it blank) // DNS-O-MATIC动态IP密码 (不使用动态IP则留空) property LastfmUsername : “**” – last.fm User Name (or leave it blank) // last.fm帐号 (不使用last.fm则留空) property LastfmPassword : “**” – last.fm Password (or leave it blank) // last.fm密码 (不使用last.fm则留空) property appStList : {“App 1”, “软件2”,”iChat”} – these apps will launch while you are online (or leave it blank) // 填写【在线】时需【开启】的软件(不使用此功能则留空) property appQuitList : {“App 1”, “软件2”,”QQ”} – these apps will quit while you are offline (or leave it blank) // 填写【离线】时需【关闭】的软件(不使用此功能则留空) *) (* ======= Variable Declaration ======= *) global timeTry global DNSResponse global isOLast global iTsCurDBID global iTsORSoundVolume global strSNGArtist global strSNGName global strSNGAlbum global strSNGTrackNumber global strSNGDuration global intIdleCount (* ======= Main Script ======= *) on run set isOLast to “” set iTsCurDBID to “” set intIdleCount to 10 end run on quit if isOLast is “online” then fnTwitter(“I am offline now! // “ & (current date), true) fnShellSSHEnd(true) fnAppQuit() continue quit end quit on idle if fnCheckNet() is true then if intIdleCount > 9 then fnSSHCnt() if isOLast is not “online” then fnAppStart() fnDNSUpdate() fnTwitter(“I am online now! // “ & (current date), true) end if set intIdleCount to 0 end if fnMusic(true) set intIdleCount to intIdleCount + 1 set isOLast to “online” else fnMusic(false) if isOLast is not “offline” then fnShellSSHEnd(true) fnAppQuit() end if set isOLast to “offline” end if return 33 end idle (* ======= Functions ======= *) to fnCheckNet() try do shell script “curl –connect-timeout 33 “apple.com/favicon.ico “” if isOLast is not “online” then SmartSay({“Online”}) return true on error if isOLast is not “offline” then SmartSay({“Offline”}) return false end try end fnCheckNet to fnAppStart() if (count appStList) > 0 then SmartSay({“Start Apps”}) try repeat with intSti from 1 to (count appStList) tell application (item intSti of appStList) to activate end repeat SmartSay({“OK”}) on error SmartSay({“Failed”}) end try end if end fnAppStart to fnAppQuit() if (count appQuitList) > 0 then SmartSay({“Quit Applications”}) try repeat with intSti from 1 to count appQuitList tell application (item intSti of appQuitList) to quit end repeat SmartSay({“OK”}) on error SmartSay({“Failed”}) end try end if end fnAppQuit to fnSSHCnt() if (length of SSHServerName) > 0 and (length of SSHUserName) > 0 and (length of SSHPasswd) > 0 then set timeTry to 0 repeat while fnCheckSSHD() is false SmartSay({“Connect SSH D”}) if timeTry > 0 then if (button returned of (display dialog “ssh -D connection failed.” & return & “” buttons {“Retry”, “Ignore”})) is “Ignore” then exit repeat fnShellSSH() set timeTry to timeTry + 1 end repeat end if end fnSSHCnt to fnCheckSSHD() try do shell script “curl –socks5 127.0.0.1:7070 –connect-timeout 33 “apple.com/favicon.ico”” if timeTry > 0 then SmartSay({“OK”}) return true on error if timeTry > 0 then SmartSay({“Failed”}) return false end try end fnCheckSSHD to fnShellSSH() try try do shell script “killall Terminal” end try tell application “Terminal” activate fnShellSSHEnd(false) of me delay 1 do script “nohup ssh -D 7070 “ & SSHUserName & “@” & SSHServerName & “ > Downloads/.Flora_ssh-D.out” in window 1 end tell SmartSay({“SSH D connection request and log in request have been sent. Waiting for response from remote server.”}) tell application “Terminal” do script SSHPasswd in window 1 delay 1 quit end tell end try end fnShellSSH to fnShellSSHEnd(isSay) if (length of SSHServerName) > 0 and (length of SSHUserName) > 0 and (length of SSHPasswd) > 0 then if isSay is true then SmartSay({“Disconnect SSH D”}) try do shell script “killall ssh” do shell script “killall ssh-agent” do shell script “rm ~/Downloads/.Flora_ssh-D.out” end try end if end fnShellSSHEnd to fnTwitter(strTwText, isSay) if (length of TwitterUsername) > 0 and (length of TwitterPassword) > 0 and (length of strTwText) > 0 then if (length of strTwText) > 140 then set strTwText to (characters 1 through 137 of strTwText as string) & “…” end if if isSay is true then SmartSay({“Update Twitter state”}) try do shell script “curl –connect-timeout 33 –user “ & (quoted form of (TwitterUsername & “:” & TwitterPassword)) & “ –data-binary “ & (quoted form of (“status=” & strTwText)) & “ “https://twitter.com/statuses/update.json”” if isSay is true then SmartSay({“OK”}) on error if isSay is true then SmartSay({“Failed”}) else SmartSay({“Update Twitter state failed”}) end if end try end if end fnTwitter to fnDNSShell() try set DNSResponse to (do shell script “curl –connect-timeout 33 “https://” & DNSUsername & “:” & DNSPassword & “@updates.dnsomatic.com/nic/update?&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG””) if first word of DNSResponse is “good” then – (second word of DNSResponse) is IP address return true else return false end if on error return false end try end fnDNSShell to fnDNSUpdate() if (length of DNSUsername) > 0 and (length of DNSPassword) > 0 then SmartSay({“Update dynamic IP”}) if fnDNSShell() is true then SmartSay({“OK”}) else SmartSay({“Failed”}) end if end if end fnDNSUpdate to fnURLec(strToUEC) return do shell script “python -c ‘import sys, urllib; print urllib.quote(sys.argv[1])’ “” & strToUEC & “”” end fnURLec to fniTunesisActive() tell application “System Events” to return (name of processes contains “iTunes”) end fniTunesisActive to fuisiTunesNUD() if fniTunesisActive() is true then tell application “iTunes” if player state is playing then set iTsNewDBID to (get database ID of current track) if iTsNewDBID is not iTsCurDBID then set strSNGArtist to (get artist of current track) set strSNGName to (get name of current track) set strSNGAlbum to (get album of current track) set strSNGTrackNumber to (get track number of current track) set strSNGDuration to (get duration of current track as integer) set iTsCurDBID to iTsNewDBID return true else

热烈庆祝!China GFW引用本站文章!

这两天GTalk上一下子很多朋友加我,都是询问Flora_ssh-D脚本的问题的。 我就纳闷心想我的Blog流量并没有那么大呀,后来才知道原来脚本被China GFW转载了。 转载地址是:http://www.chinagfw.org/2009/10/blog-post_1289.html // PS:访问需要先翻墙。 感谢大家的支持,Flora_ssh-D经过周末的密集式的开发,目前已经升级到1.73了,1.73是比较成熟的版本,执行已经相当稳定和高效了。 有些人可能还不明白Flora_ssh-D能做什么,这里我有一个1.3版的屏幕录影,大家看看就明白了。 注意,录影为1.3版,不是最新的1.73版,1.73版的语音提醒已经升级了,补发这段视频是为了大家更加明白Flora_ssh-D的功能。 http://player.youku.com/player.php/sid/31954880/v.swf // 视频地址:http://v.youku.com/v_show/id_XMTI3ODE5NTIw.html 原计划下一步是把项目移植到X-Code,用Object-C重写的,但是由于太多朋友询问Windows是否支持这个脚本。我可能会考虑一下Flora_ssh-D在Windows上的实现。 但是由于Windows上没有如Unix上那么便利的shell,实现Flora_ssh-D的功能就需要动用更高级的开发工具了,有点小题大作了。 目前我比较想在Windows上把脚本中的iTunes VoiceOver的功能先做起来,但是Windows上开发iTunes比较困难,还没想到好的办法呢。 所以具体怎么实现,是否需要用Visual Studio写,我还在考虑中。因为周一到周五我要工作,时间也不多。 所以,Windows上怎么做,做不做,我现在还不能回答大家。 另一点就是VoiceOver使用系统的API发音,由于Mac上的语音合成API不支持中文,那么中文的歌名和艺术家就不能报读了(其实Windows上的语音引擎也一样)。 但是Apple提供给iPod使用的VoiceOver Kit是能够支持多语言的,所以iPod shuffle会说20种语言,包括中文。而Mac上的API不知道为什么就是不支持,这个问题也有待研究了。 谢谢大家支持! 提醒大家,Flora_ssh-D已经在Google Code上开源,项目地址是:http://code.google.com/p/flora-ssh-d/ /* 还有另一个值得庆祝的就是我发布的SX1_RU06_LSK_UNLOCK(用于解锁SX1的软件包)在Box.net上已经录得超过20110 times的下载量了! 但是提醒一下SX1解锁的研究已经停止很久了,我的机器也已经坏了,大家不用再找我了,不然我真的很怕上线了(太多人找)。大家Google一下就能找到我的教程,然后下载下面的包,刷进去,重启就可以了。 下载地址(天朝网民需翻墙): SX1_RU06_LSK_UNLOCK.part1.rar SX1_RU06_LSK_UNLOCK.part2.rar 墙内下载地址: SX1_RU06_LSK_UNLOCK.part1.rar SX1_RU06_LSK_UNLOCK.part2.rar */

天朝春色关我不住,一段代码让我出墙来(Flora_ssh-D 1.73隆重发布!)

Flora_ssh-D 1.73已经不单单是翻墙脚本了,目前我计划把Flora_ssh-D发展成一个自动化的助理,让你的电脑用得更舒心。 目前的功能如下: 自动检查网络状态,根据在线和离线的状态为你开启和关闭软件;- 自动检查ssh -D的连接状态,如果断开了会为你自动连接,连接失败将提示自动重连,使用后墙对你来说基本上是透明的;- VoiceOver语音功能,这个功能和iPod一样,你的iTunes在播放的时候能够语音提示你正在播放的歌名和艺术家名字;- 语音提醒功能的改进,当需要语音提示用户操作的时候,如果你的iTunes正在播放,将自动降低你的iTunes音量,在语音提示结束后还原音量;- 使用API自动将你正在收听的音乐记录到Last.fm,你已经不再需要额外的iTunes插件来记录了;- 使用API自动更新你在DNS-O-MATIC上的动态IP,你不再需要其他额外的软件更新动态IP了;- 新版本使用新的idle时间管理,对比上一个版本有很大的效能提升,后台的常驻几乎不占用任何资源。 Google Code上下载地址如下:http://code.google.com/p/flora-ssh-d/downloads/list (包含源代码) // PS: 使用翻墙功能你需要先有SSH帐号,使用其他功能则不需要。 源代码如下: (* Flora_ssh-D // Version 1.73 // Code by Leask Huang // www.leaskh.com // i@leaskh.com *) (* ======= Variable Declaration ======= *) global timeTry global DNSResponse global isOLast global iTsCurDBID global iTsORSoundVolume global strSNGArtist global strSNGName global strSNGAlbum global strSNGTrackNumber global strSNGDuration (* ======= General Settings ======= ) ( Custom these before you run this script ) property SSHServerName : “.**.com” – Set ssh -D ServerName (or leave it blank) property SSHUserName : “**” – Set UserName (or leave it blank) property SSHPasswd : “**” – Set Password (or leave it blank) property TwitterUsername : “**” – If you don’t want to update Twitter status, leave it blank property TwitterPassword : “**” – same as above property TwitterText : “@” & TwitterUsername & “ is online now! // “ & (current date) – same as above property DNSUsername : “**” – Set DNS UserName (or leave it blank) property DNSPassword : “**” – Set Password (or leave it blank) property LastfmUsername : “**” – Set Last.fm UserName (or leave it blank) property LastfmPassword : “**” – Set Password (or leave it blank) property appStList : {“”, “”} – these aplications will launch while you are online (or leave it blank) property appQuitList : {“”, “***”} – these aplications will quit while you are offline (or leave it blank) (* ======= Main Script ======= *) on run set isOLast to “” set iTsCurDBID to “” end run on quit continue quit end quit on idle if fnCheckNet() is true then fnSSHCnt() if isOLast is not “online” then fnAppStart() fnDNSUpdate() fnTwitter() end if fnLastfm() set isOLast to “online” else if isOLast is not “offline” then fnAppQuit() set isOLast to “offline” end if return 180 end idle (* ======= Functions ======= *) to fnCheckNet() try do shell script “curl –connect-timeout 33 “apple.com/favicon.ico”” if isOLast is not “online” then SmartSay(“Online”) return true on error if isOLast is not “offline” then SmartSay(“Offline”) return false end try end fnCheckNet to fnAppStart() if (count appStList) > 0 then SmartSay(“Start Apps”) try repeat with intSti from 1 to (count appStList) tell application (item intSti of appStList) to activate end repeat SmartSay(“OK”) on error SmartSay(“Failed”) end try end if end fnAppStart to fnAppQuit() if (count appQuitList) > 0 then SmartSay(“Quit Applications”) try repeat with intSti from 1 to count appQuitList tell application (item intSti of appQuitList) to quit end repeat SmartSay(“OK”) on error SmartSay(“Failed”) end try end if end fnAppQuit to fnSSHCnt() if (length of SSHServerName) > 0 and (length of SSHUserName) > 0 and (length of SSHPasswd) > 0 then set timeTry to 0 repeat while fnCheckSSHD() is false SmartSay(“Connect SSH D”) if timeTry > 0 then if (button returned of (display dialog “ssh -D connection failed.” & return & “” buttons {“Retry”, “Ignore”})) is “Ignore” then exit repeat fnShellSSH() set timeTry to timeTry + 1 end repeat end if end fnSSHCnt to fnCheckSSHD() try do shell script “curl –socks5 127.0.0.1:7070 –connect-timeout 33 “apple.com/favicon.ico”” if timeTry > 0 then SmartSay(“OK”) return true on error if timeTry > 0 then SmartSay(“Failed”) return false end try end fnCheckSSHD to fnShellSSH() try tell application “Terminal” quit delay 1 activate delay 1 do script “rm ~/Downloads/.Flora_ssh-D.out” in window 1 do script “killall ssh” in window 1 do script “killall ssh-agent” in window 1 do script “nohup ssh -D 7070 “ & SSHUserName & “@” & SSHServerName & “ > Downloads/.Flora_ssh-D.out” in window 1 end tell SmartSay(“SSH D connection request and log in request have been sent. Waiting for response from remote server.”) tell application “Terminal” do script SSHPasswd in window 1 delay 1 quit end tell end try end fnShellSSH to fnTwitter() if (length of TwitterUsername) > 0 and (length of TwitterPassword) > 0 and (length of TwitterText) > 0 then SmartSay(& quot;Update Twitter state”) try do shell script “curl –connect-timeout 33 –user “ & (quoted form of (TwitterUsername & “:” & TwitterPassword)) & “ –data-binary “ & (quoted form of (“status=” & TwitterText)) & “ “https://twitter.com/statuses/update.json”” SmartSay(“OK”) on error SmartSay(“Failed”) end try end if end fnTwitter to fnDNSShell() try set DNSResponse to (do shell script “curl –connect-timeout 33 “https://” & DNSUsername & “:” & DNSPassword & “@updates.dnsomatic.com/nic/update?&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG””) if first word of DNSResponse is “good” then – (second word of DNSResponse) is IP address return true else return false end if on error return false end try end fnDNSShell to fnDNSUpdate() if (length of DNSUsername) > 0 and (length of DNSPassword) > 0 then SmartSay(“Update dynamic IP”) if fnDNSShell() is true then SmartSay(“OK”) else SmartSay(“Failed”) end if end if end fnDNSUpdate to fnURLec(strToUEC) return do shell script “python -c ‘import sys, urllib; print urllib.quote(sys.argv[1])’ “” & strToUEC & “”” end fnURLec to fniTunesisActive() tell application “System Events” to return (name of processes contains “iTunes”) end fniTunesisActive to fuisiTunesNUD() if fniTunesisActive() is true then tell application “iTunes” if player state is playing then set iTsNewDBID to (get database ID of current track) if iTsNewDBID is not iTsCurDBID then set strSNGArtist to (get artist of current track) set strSNGName to (get name of current track) set strSNGAlbum to (get album of current track) set strSNGTrackNumber to (get track number of current track) set strSNGDuration to (get duration of current track as integer) set iTsCurDBID to iTsNewDBID return true else return false end if else return false end if end tell else return false end if end fuisiTunesNUD to SmartSay(strToSay) set isiTPing to false if fniTunesisActive() is true then tell application “iTunes” to if player state is playing then set isiTPing to true end if if isiTPing is true then tell application “iTunes” set iTsORSoundVolume to sound volume set sound volume to iTsORSoundVolume * 0.333 end tell say “” & strToSay tell application “iTunes” to set sound volume to iTsORSoundVolume else say “” & strToSay end if end SmartSay to fnLastfm() if fuisiTunesNUD() is true then if (length of strSNGName) > 0 or (length of strSNGArtist) > 0 then tell application “iTunes” set iTsORSoundVolume to sound volume set sound volume to iTsORSoundVolume * 0.333 end tell if (length of strSNGName) > 0 then say strSNGName delay 1 end if if (length of strSNGArtist) > 0 then say strSNGArtist tell application “iTunes” to set sound volume to iTsORSoundVolume end if if (length of LastfmUsername) > 0 and (length of LastfmPassword) > 0 then try do shell script “curl –connect-timeout 33 “http://lastfmstats.livefrombmore.com/universalscrobbler/scrobble.php?submissionType=track” & “&username=” & LastfmUsername & “&password=” & LastfmPassword & “&artist=” & fnURLec(strSNGArtist) & “&track=” & fnURLec(strSNGName) & “&album=” & fnURLec(strSNGAlbum) & “&number=” & strSNGTrackNumber & “&duration=” & strSNGDuration & “”” on error SmartSay(“Scrobbling Failed”) end try end if end if end fnLastfm

长风破浪会有时,直挂云帆济沧海(Flora_ssh-D 1.3发布!)

Flora_ssh-D 1.3 版本发布! 本版本重新整理程序,实现模块化; 引入后台运行机制,时刻检查网络; 简化设定,功能设置只需要留空,该功能就不会执行了; 直接使用DNS-O-MATIC的API更新动态IP,不再需要额外的程序了。 不推荐升级这个版本,因为1.73版本已经开发出来了,我下一文就是发布1.73的,先发1.3是因为想保持版本的连续性。大家可以忽略。 Google Code上的下载地址为:http://code.google.com/p/flora-ssh-d/downloads/list (包含源代码) 代码如下: (* Flora_ssh-D // Version 1.3 // Code by Leask Huang // www.leaskh.com // i@leaskh.com *) (* ======= Variable Declaration ======= *) global timeTry global DNSResponse global isOLast (* ======= General Settings ======= ) ( Custom these before you run this script *) set SSHServerName to “**” – Set ServerName, You must set this set SSHUserName to “**” – Set UserName, You must set this set SSHPasswd to “**” – Set Password, You must set this set TwitterUsername to “**” – If you don’t want to update Twitter status, leave it blank set TwitterPassword to “**” – same as above set TwitterText to “@” & TwitterUsername & “ is online now! // “ & (current date) – same as above set DNSUsername to “**” set DNSPassword to “***” set appStList to {“Adium”, “CoverSutra”, “Google Notifier”} – these aplications will launch while you are online (or leave it blank) set appQuitList to {“CoverSutra”, “Google Notifier”} – these aplications will quit while you are offline (or leave it blank) (* ======= Advanced Settings ======= ) ( You don’t need to change these normally *) (* ======= Main Script ======= *) set isOLast to “” repeat delay 10000 end repeat repeat if fnCheckNet() is true then if isOLast is not “online” then fnSSHCnt() fnAppStart() fnDNSUpdate() fnTwitter() end if set isOLast to “online” say “All done!” else if isOLast is not “offline” then fnAppQuit() end if set isOLast to “offline” say “All done!” end if – delay 333 delay 60 end repeat (* ======= Functions ======= *) to fnCheckNet() try do shell script “curl –connect-timeout 7 apple.com/favicon.ico” if isOLast is not “online” then say “Great! You are online.” end if return true on error if isOLast is not “offline” then say “Opps! You are offline.” end if return false end try end fnCheckNet to fnCheckSSHD() try do shell script “curl –socks5 127.0.0.1:7070 –connect-timeout 7 apple.com/favicon.ico” say “OK! SSH D has been successfully connected.” return true on error if timeTry > 0 then say “Opps! SSH D connection failed.” end if return false end try end fnCheckSSHD to fnAppStart() if (count appStList) > 0 then say “Start Applications” try repeat with intSti from 1 to (count appStList) tell application (item intSti of appStList) activate end tell end repeat on error say “Opps! Error.” end try end if end fnAppStart to fnAppQuit() if (count appQuitList) > 0 then say “Quit Applications” try repeat with intSti from 1 to count appQuitList tell application (item intSti of appQuitList) quit end tell end repeat on error say “Opps! Error.” end try end if end fnAppQuit to fnSSHCnt() if (length of SSHServerName) > 0 and (length of SSHUserName) > 0 and (length of SSHPasswd) > 0 then set timeTry to 0 say “Create SSH D connection” repeat while fnCheckSSHD() is false if timeTry > 0 then if (button returned of (display dialog “Opps! ssh -D connection failed. Do you want to retry?” & return & “” buttons {“Retry”, “Quit”})) is “Quit” then exit repeat end if end if fnShellSSH() set timeTry to timeTry + 1 end repeat end if end fnSSHCnt to fnShellSSH() try tell application “Terminal” quit delay 1 activate delay 1 do script “rm ~/Downloads/.Flora_ssh-D.out” in window 1 do script “killall ssh” in window 1 do script “killall ssh-agent” in window 1 do script “nohup ssh -D 7070 “ & SSHUserName & “@” & SSHServerName & “ > Downloads/.Flora_ssh-D.out” in window 1 end tell say “SSH D connection request and log in request have been sent. Waiting for response from remote server.” tell application “Terminal” do script SSHPasswd in window 1 delay 1 quit end tell on error say “Opps! Error.” end try end fnShellSSH to fnTwitter() if (length of TwitterUsername) > 0 and (length of TwitterPassword) > 0 and (length of TwitterText) > 0 then say “Update Twitter state” try do shell script “curl –user “ & (quoted form of (TwitterUsername & “:” & TwitterPassword)) & “ –data-binary “ & (quoted form of (“status=” & TwitterText)) & “ https://twitter.com/statuses/update.json” say “OK! Twitter state has been successfully updated.” on error /> say “Opps! Error.” end try end if end fnTwitter to fnDNSShell() try set DNSResponse to (do shell script “curl https://” & DNSUsername & “:” & DNSPassword & “@updates.dnsomatic.com/nic/update?&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG”) if first word of DNSResponse is “good” then return true else return false end if on error return false end try end fnDNSShell to fnDNSUpdate() if (length of DNSUsername) > 0 and (length of DNSPassword) > 0 then say “Update dynamic IP” if fnDNSShell() is true then say “OK! Dynamic IP has been successfully updated to “ & (second word of DNSResponse) else say “Opps! Error.” end if end if end fnDNSUpdate

Mac上使用固定域名解释到动态IP的方法(类似于“花生壳”的用法)

Mac上使用固定域名解释到动态IP的方法(类似于“花生壳”的用法)

很多人都有需要把固定域名解释到动态IP,因为很多人想在自己的电脑上提供主机服务,但是又苦于ISP提供的是动态IP而非固定IP。 怎么办呢?Windows上有“花生壳”(请自行Google),那么Mac上呢?其实Mac上也有简便的解决方案的。 实现固定域名解释到动态IP,我们需要满足两个条件: 我们首先需要一个支持实时修改IP地址映射的DNS服务器; 我们还需要一个上传本地IP地址到远程DNS服务器的客户端程序。 OK,我们来一个一个解决。 第一个问题我们可以通过D-Link Dynamic DNS解决,该服务目前免费。注册地址是:https://www.dlinkddns.com/ 注册后会得到一个域名,然后你可以填上你当前的IP地址。 那么你已经能让全球的朋友通过这个域名访问你的电脑了,那么问题是如果你的IP改变了,是不是就需要重新登录这个页面填写新的IP呢?所以我们需要接着解决第二个问题。 第二个问题我们可以通过DNS-O-Matic解决,该服务目前免费。注册地址是:https://www.dnsomatic.com/ DNS-O-Matic是不提供DNS服务的,它关注的是更新各种DNS服务上的动态IP地址,DNS-O-Matic支持上面提到的D-Link Dynamic DNS,同时也支持OpenDNS。 DNS-O-Matic的注册也同样简单,注册后你可以添加你所使用的DNS服务,如输入你的D-Link Dynamic DNS帐号、密码和域名。 为什么要引入DNS-O-Matic呢?因为DNS-O-Matic支持开放式的API,你可以通过各种形式的客户端或者脚本来更新你提交你的本地IP地址。 如以下这个Mac上的小脚本DNS-O-Matic Updater就是我们所需要的了: http://web.me.com/zweigand/zweisoft/Software/Entries/2009/1/13_DNS-O-Matic_Updater_1.4.html 下载并填写你的DNS-O-Matic帐号就OK了,以后只需要启动这个小脚本,就能自动更新你的动态IP了哦。 使用起来,比“花生壳”还要便捷,而且一切都是免费的。 对了,最后提一下,如果你自己有一个域名,那么可以把自己的域名CNAME到你的D-Link Dynamic DNS域名,就能实现通过自己的域名,任何时候都能访问你的电脑了。 // 最后预告一下,Flora_ssh-D,也就是我的翻墙脚本的下一个版本也将直接使用DNS-O-Matic的API而不是调用DNS-O-Matic_Updater来更新动态IP了,敬请关注。

我优雅一转身,墙应声而倒。我挥一挥衣袖,不带走一片砖瓦。

我优雅一转身,墙应声而倒。我挥一挥衣袖,不带走一片砖瓦。

又到了周末翻墙的时间了。 使用了一段时间的ssh -D,我终于找回了做人的感觉,自由的空气如此新鲜,信息的绿洲让人神往,流连忘返。 ssh -D如此便利,速度如此流畅,让人印象深刻,但是美中不足的是每次都需要先连接,虽然上次已经分享过我写的一段脚本,实现在Mac上自动翻墙。但上次的脚本比较粗糙,仓促,于是又有了一些新的想法,目标是让翻墙更优雅、潇洒。 上次的版本是0.3,这次改动比较大我把版本设置为0.7,下面简单说一下几点改进: 自动判断在线状态,如果你还没有上网,是不会执行翻墙程序的; 自动判断翻墙结果,如果翻墙失败,程序将自动重新尝试; 自动更新动态IP,你或许在自己的电脑上使用OpenDNS,host网站,或者其他原因需要更新动态IP(近段时间我将发文谈谈Mac上动态IP的问题,请关注); 自动执行程序,如果你有一些程序,如聊天软件,邮件检查软件等需要在上网的时候开启,也可以设定; 自动退出程序,如果你有一些程序,如邮件检查程序,Last.fm等,需要在断网的时候关闭,也可以设定; 设定是否在翻墙成功的时候更新Twitter状态; 全程语音提示,告诉你程序目前正在干什么,十分Cool; 主要也就7点打改进,新的脚本还包含了错误语音提示,当过程中发生错误,将语音提醒你是什么原因发生错误。 十分建议把脚本设置为开机执行。 程序已经提交到Google Code,并开放源代码: 地址如下:http://code.google.com/p/flora-ssh-d/ 注意!访问Google Code你可能需要先翻墙。 下面贴出源代码,大家粘贴到AppleScript Editor.app里面,修改参数然后执行就可以了。 有不明白的可以邮件或者GTalk联系我,我的邮件/GTalk/MSN/QQ同为:i@leaskh.com 。 (* Flora_ssh-D // Version 0.7 // Code by Leask Huang // www.leaskh.com // i@leaskh.com *) (* ======= Variable Declaration ======= *) global YourName global SSHServerName – SSH Server Name global SSHLocalPorts – Local Port global SSHUserName – User Name on SSH Server global SSHPasswd – Password for SSH Server global TwitterAPI – Twitter API URL global TwitterUsername – Twitter User Name global TwitterPassword – Twitter Password global TwitterLogin global TwitterStatus global JobID global URLTestNet global URLTestGFW global appDNSUpdate global appStList global appQuitList global isConnected global isSSHCnt global isUpdateTwitter global isRunExSoft global isQuitExSoftware global isUpdateDNS global isDelnohup global strnohup global timeTry global isforceQuit (* ======= General Settings ======= ) ( You don’t need to change these normally *) set URLTestGFW to “twitter.com” – Use this URL to check is your are Blocked by GFW set URLTestNet to “leask.com” – Use this URL to check if you are online set SSHLocalPort to “7070” – Set Socks 5 local port set TwitterAPI to “https://twitter.com/statuses/update.json” – Twitter API URL – set TwitterAPI to “http://twitter.com/statuses/update.json” – Simple HTTP Twitter API URL (NOT Recommend) set isDelnohup to true – Set it as true to del SSH output informtions every time set strnohup to “Downloads/.Flora_ssh-D.out” – Config your SSH output file location set isUpdateDNS to true – Config if you want to update your dynamic IP address for OpenDNS / DLinkDDNS / DynDNS set isUpdateTwitter to true – Config if you want to update Twitter status every time set isRunExSoft to true – Config if you want to launch some aplications when you are online set isQuitExSoftware to true – Config if you want to quit some aplications when you are offline (* ======= User Settings ======= ) ( Custom these before you run this script ) set SSHServerName to “.**.com” – Set ServerName, You must set this set SSHUserName to “**” – Set UserName, You must set this set SSHPasswd to “*****” – Set Password, You must set this set TwitterUsername to “” – If you don’t want to update Twitter status, leave it blank set TwitterPassword to “” – same as above set TwitterText to “@” & TwitterUsername & “ is online now! // “ & (current date) – same as above set appDNSUpdate to “DNS-O-Matic Updater” – Use this application to update your dynamic IP address (or leave it blank) set appStList to {“Adium”, “CoverSutra”, “Google Notifier”} – these aplications will launch while you are online (or leave it blank) set appQuitList to {“CoverSutra”, “Google Notifier”} – these aplications will quit while you are offline (or leave it blank) (* ======= Main Script ======= *) set isConnected to false set isSSHCnt to false set timeTry to 0 set isforceQuit to false try do shell script “curl “ & URLTestNet set isConnected to true on error set isConnected to true – false say “Opps! Your internet isn’t ready.” if (isQuitExSoftware is true) and ((count appQuitList) > 0) then repeat with intSti from 1 to count appQuitList tell application (item intSti of appQuitList) quit end tell end repeat end if end try if isConnected is true then repeat while isSSHCnt is false tell application “System Events” if exists process “Terminal” then tell application “Terminal” quit end tell delay 3 tell application “Terminal” activate end tell else tell application “Terminal” activate end tell end if end tell if (isUpdateDNS is true) and ((length of appDNSUpdate) > 0) and (timeTry is 0) then tell application appDNSUpdate activate end tell end if tell application “Terminal” if (isDelnohup is true) and (timeTry is 0) then do script “rm ~/” & strnohup in window 1 delay 1 end if do script “killall ssh” in window 1 delay 1 do script “killall ssh-agent” in window 1 delay 1 do script “nohup ssh -D “ & SSHLocalPort & “ “ & SSHUserName & “@” & SSHServerName & “ > “ & strnohup in window 1 end tell if timeTry is 0 then say “Hi, “ & (short user name of (system info)) & “. I am your Mac. I am configuring the network for you.” set JobID to 1 if isUpdateDNS is true then say “Process “ & JobID & “: Update DNS” set JobID to JobID + 1 end if else set JobID to JobID + 1 say “Process “ & JobID & “: Update DNS” set JobID to JobID + 1 say “Process “ & JobID & “: Get ready to retry.” end if tell application “Terminal” do script SSHPasswd in window 1 end tell say “Process “ & JobID & “: Create SSH D connection” try do shell script “curl –socks5 127.0.0.1:” & SSHLocalPort & “ “ & URLTestGFW say “OK! SSH D has been successfully connected.” set isSSHCnt to true on error set isSSHCnt to false say “Opps! SSH D connection fail.” if (button returned of (display dialog “Opps! ssh -D connection fail. Do you want to retry?” & return & “” buttons {“Retry”, “Quit”})) is “Retry” then set timeTry to timeTry + 1 else exit repeat end if end try end repeat if isSSHCnt is true then if (isUpdateTwitter is true) and ((length of TwitterUsername) > 0) and ((length of SSHPasswd) > 0) and ((length of TwitterText) > 0) then try set JobID to JobID + 1 say “Process “ & JobID & “: Update twitter state” set TwitterLogin to quoted form of (TwitterUsername & “:” & TwitterPassword) set TwitterStatus to quoted form of (“status=” & TwitterText) do shell script “curl –user “ & TwitterLogin & “ –data-binary “ & TwitterStatus & “ “ & TwitterAPI say “OK! Twitter state has been successfully updated.” on error say “Opps! Error while updating Twitter state.” end try end if if (isRunExSoft is true) and ((count appStList) > 0) then set JobID to JobID + 1 say “Process “ & JobID & “: Start Applications” repeat with intSti from 1 to count appStList tell application (item intSti of appStList) activate end tell end repeat end if end if tell application “Terminal” quit end tell if (isUpdateDNS is true) and ((length of appDNSUpdate) > 0) then tell application appDNSUpdate quit end tell end if say “All done! Bye!” end if

我的第一个Adium Xtra:Snow Leopard iChat

我的第一个Adium Xtra:Snow Leopard iChat

收到来自Adium的邮件: from xtras@adiumxtras.com sender-time Sent at 8:36 PM (UTC). Current time there: 6:00 AM. ✆ to i@leaskh.com date Fri, Oct 23, 2009 at 8:36 PM subject Your Xtra Was Approved hide details 8:36 PM (17 hours ago) Your Xtra, Snow Leopard iChat, was just approved: http://adiumxtras.com/index.php?a=xtras&xtra_id=7119 意味着我的第一个Adium Xtra已经通过官方验证,发布在Adium Xtra官网上面了。 Adium相信是Mac用户都应该知道了,是一个很棒的多协议IM软件 Adium Xtra是Adium的插件架构,该架构通过很多便捷接口把Adium插件开发简化到一个惊人的地步。 只需要懂XML、CSS、Applescript等,就能开发出很好玩的Adium插件了。 这也是我近段时间放弃iChat转投Adium的其中一个原因,当然,另一个原因是Adium支持Windows Live Messenger和Facebook IM等。 好了,上图吧: 我的Snow Leopard iChat安装后,能够让你的Adium在Dock中显示和iChat 5一样的ICON,因为虽然Adium的小鸭子很可爱,但是很多Mac用户都怀念iChat图标的优雅。 喜欢的朋友去下载吧:http://adiumxtras.com/index.php?a=xtras&xtra_id=7119 这次仅仅是试验一下Adium Xtra的插件架构,在我使用Adium的过程中,我发现其实通过目前web 2.0网站的众多API,我们可以做到很多很有趣的事情,例如douban就很有趣,但是douban的机器人一直做得不怎么样。通过Adium的Xtra让douban和IM做整合,就能做出很多有趣的事儿。 等有时间吧,等我的i3机器人开发好了,我会想一下这个问题。 但是最近公司的事情也挺忙呢,不知道要等到何年何月了。