本文主要讲述如何通过多种设备(PC,Mac,iOS、Andriod 设备)远程撰写及发布基于 Octopress
系统的博客。
工作流程是:远程撰写,然后通过 Dropbox 同步文章到装有 Octopress 构建环境的电脑上,再自动触发 rake 命令生成网站并发布。
推荐将 Octopress 构建环境安装在 VPS 或者专用服务器上,或者一台常开并可以访问外网的电脑上。如果是多人使用的电脑,强烈建议安装一个 Linux 的虚拟机,在虚拟机中配置 Octopress 构建环境。给虚拟机设上密码,保证您的信息安全。虚拟机还能带来一定程度的移动性。
Octopress
通常由三个部分组成:
Octopress
文章的源文件。例如 Windows PC, Mac, Android 手机,iOS 设备等。基于构建环境的复杂性,在手机等移动设备上搭建 Octopress
在目前看来还是比较困难的。
Octopress
的方案:
Octopress
的相应目录,并调用 rake 命令生成和发布博客。优点:实现了远程发布;多种终端支持(PC,手机,平板等);邮件有备份作用。
缺点:你需要一个支持 pop3 的邮箱;要以约定的格式来撰写邮件,还需要注意使用纯文本格式来发送邮件。
Dropbox
同步文件到构建环境中 Octopress
的相应目录优点:实现了远程发布;多终端支持(Dropbox 支持的终端很多);具有备份作用(Dropbox 本身就可当做备份工具)。
缺点:远程登录不是很方便。首先构建环境不一定都能被访问到(如在 NAT 网络中),其次并不是所有设备都能安装需要的远程客户端。
Octopress
中特定目录优点:实现了远程发布;具有备份和版本管理功能。
缺点:能安装 GIT 客户端的设备有限,限于 PC, Mac 等设备,具有越狱后的 iOS 设备也可以安装,没有亲自试过。
Dropbox
,所以在上述第二种方案上进行了改造,实现了自己的工作流程。
Dropbox
的设备撰写文章Dropbox
自动同步文章到构建环境中 Octopress
的 source 目录Octopress source
目录的变动,发现变动后调用 rake 调用 rake 命令生成和发布博客一般的办法是通过定时任务定时扫描 Octopress
目录变化。例如使用 Linux 的 cron,Windows 的 计划任务 或者你自己编写的程序。
较好的办法就是利用文件系统事件监听机制监听目录或文件变化,例如 Linux 的 inotify
机制和 Windows 的 ReadDirectoryChangesW。
本文下面的示例、代码等都是以 Linux(CentOS 6)
做为构建环境来描述的,有兴趣在 Windows 下配置这个机制的,请参考文章末尾的一些资源。
Windows 下请阅读这篇文章。
这个步骤完成后,假设将 Octopress
通过 git clone 到了 /root/octopress
目录。
#cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86" | tar xzf -64-bit:
#cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -接着,从新建的 .dropbox-dist 文件夹运行
Dropbox
守护程序。
#~/.dropbox-dist/dropboxd启动后会提示 Dropbox 客户端还没有链接到相关账户,并显示一个链接,如 https://www.dropbox.com/cli_linux?host_id=XXXXXX ,复制链接到浏览器(不一定是构建环境所在的电脑),登录 Dropbox,此时在构建环境的电脑的 /root 目录中将会产生 Dropbox 目录,并且已经同步了 Dropbox 中的内存到该目录。这个登录链接过程一般只需要做一次,如果以后启动 Dropbox 还提示需要链接,做同样操作即可。
接着,下载 Dropbox 控制脚本,便于我们管理 Dropbox。
#cd ~ #wget http://www.dropbox.com/download?dl=packages/dropbox.py #chmod +x dropbox.py可以使用以下命令启动、停止和查看 Dropbox 状态
#~/dropbox.py start #~/dropbox.py stop #~/dropbox.py status为了开机时自动启动 Dropbox,我编写了一个叫着 dropboxd 的 Linux 服务脚本。
文件名 dropboxd
#!/bin/sh # # chkconfig: 2345 19 81 # description: Dropbox daemon service. # processname: dropboxd # call: /etc/init.d/dropboxd # DROPBOX_SHELL=/root/dropbox.py # See how we were called. case "${'$'}1" in start) ${'$'}DROPBOX_SHELL start ;; stop) ${'$'}DROPBOX_SHELL stop ;; status) ${'$'}DROPBOX_SHELL status ;; *) echo "Usage: {start | stop | status}" exit 1 ;; esac exit 0将脚本文件上传到构建文件的 /etc/init.d/ 目录下,并修正权限
#chmod +x /etc/init.d/dropboxd设置成开机自动启动
#chkconfig --add dropboxd调用 Linux Service 命令
#service dropboxd start #service dropboxd stop #service dropboxd status将
Octopress
的 source 目录链接到 Dropbox 中,以便于 Dropbox 进行同步
#ln -s /root/octopress/source /root/Dropbox/octopress_source如果 Dropbox 服务是启动的,此时登录 Dropbox 网页版,应该可以看到
octopress_source
下的内容已经同步了。同样之后如果在移动端添加文件到这个目录,也会同步到构建环境中。
/root/octorake.sh
#!/bin/sh cd /root/octopress /root/.rbenv/shims/rake generate /root/.rbenv/shims/rake deploy注意,如果不是使用 rbenv 安装 ruby 的,要修改上面的脚本。通过
which rake
查找 rake 路径。
安装要求
Linux 内核版本 ≥ 2.6.13 Python 版本 ≥ 2.4 (including Python 3.x)由于在之前的安装过程中已经安装了 git 和 python,这里可以调用以下命令安装 Pyinotify
#cd ~ #git clone git://github.com/seb-m/pyinotify.git #cd pyinotify #python setup.py install
Octopress
相应目录的变化,这个脚本笔者称之为 octowatcher。这个是笔者自定义工作流程的核心部分。
脚本路径 /root/octowatcher.py
#!/usr/bin/python import pyinotify import subprocess OCTOPRESS_RAKE_SHELL="/root/octorake.sh" WATCH_TARGET="/root/Dropbox/octopress_source/" WATCH_FILE="/root/Dropbox/octopress_source/trigger.txt" def checkevent(eventname, pathname): if pathname == WATCH_FILE: #print eventname, ": /root/Dropbox/octopress_source/trigger.txt changed, call rake ..." p = subprocess.Popen(OCTOPRESS_RAKE_SHELL, close_fds=True, bufsize=1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p.communicate() class OctopressSourceModifyHandler(pyinotify.ProcessEvent): def process_IN_ATTRIB(self, event): #print "ATTRIB event:", event.pathname checkevent("ATTRIB", event.pathname) def process_IN_MODIFY(self, event): #print "MODIFY event:", event.pathname checkevent("MODIFY", event.pathname) def main(): wm = pyinotify.WatchManager() #pyinotify.IN_MODIFY, pyinotify.ALL_EVENTS wm.add_watch(WATCH_TARGET, pyinotify.IN_ATTRIB + pyinotify.IN_MODIFY, rec=True) eh = OctopressSourceModifyHandler() notifier = pyinotify.Notifier(wm, eh) #notifier = pyinotify.Notifier(wm); notifier.loop() if __name__ == '__main__': main()这里有必要说明一下,之前一直描述如何监听
Octopress
的 source 目录变动,而脚本中只监听一个 source 下一个指定文件的变动。
如果监听整个目录的变动,当文章还没有写完就保存时,Dropbox 同步后也会执行构建脚本,这样可能导致将还没有写完的文章发布出去。有时甚至文件的格式都还不完整,导致 rake 失败。
所以笔者的做法,是在写完文章保存后,修改一下 trigger.txt 的文件(随便该点啥)并保存,系统监听到 trigger.txt 的变化才执行构建命令。
另外只监听了 IN_ATTRIB 和 IN_MODIFY 事件,经过观察,dropbox 同步的特征事件是 IN_ATTRIB, 而通过 echo 测试直接修改 trigger.txt 内容的特征事件是 IN_MODIFY。
当然,这其实不算一种比较优美的方式。
执行该脚本
#~/octowatcher.py在后台运行
#~/octowatcher.py &同样,如果需要在开机自动运行该脚本,可以写一个 Linux 服务脚本
文件名 octowatcher
#!/bin/sh # # chkconfig: 2345 20 80 # description: Octopress modify watcher service. # processname: octowatcher # call: /etc/init.d/octowatcher # WATCHER_USER=root WATCHER_SHELL=/root/octowatcher.py WATCHER_PNAME=octowatcher.py # See how we were called. case "${'$'}1" in start) PID=`pgrep -u ${'$'}WATCHER_USER ${'$'}WATCHER_PNAME` if [ -z ${'$'}PID ] ; then echo "Starting octowatcher ..." ${'$'}WATCHER_SHELL & else echo "octowatcher for user ${'$'}WATCHER_USER is running (pid ${'$'}PID)" fi ;; stop) #pkill -x ${'$'}WATCHER_PNAME PID=`pgrep -u ${'$'}WATCHER_USER ${'$'}WATCHER_PNAME` if [ -z ${'$'}PID ] ; then echo "octowatcher for user ${'$'}WATCHER_USER not running." else echo "Found octowatcher for user ${'$'}WATCHER_USER at pid ${'$'}PID" echo "Killing ...." kill -9 ${'$'}PID RESULT=${'$'}? if [ ${'$'}{RESULT} -eq 0 ]; then echo "Successs" else echo "Failed, exit code ${'$'}RESULT" fi fi ;; status) PID=`pgrep -u ${'$'}WATCHER_USER ${'$'}WATCHER_PNAME` if [ -z ${'$'}PID ] ; then echo "octowatcher for user ${'$'}WATCHER_USER: not running" else echo "octowatcher for user ${'$'}WATCHER_USER: running (pid ${'$'}PID)" fi ;; *) echo "Usage: {start | stop | status}" exit 1 ;; esac exit 0将脚本文件上传到构建环境所在机器的 /etc/init.d/ 目录下,并修正权限
#chmod +x /etc/init.d/octowatcher设置成开机自动启动
#chkconfig --add octowatcher调用 Linux Service 命令
#service octowatcher start #service octowatcher stop #service octowatcher status检验 octowatcher 脚本是否正常运行
启动 octowatcher 服务后,执行以下脚本
#echo test>>/root/Dropbox/octopress_source/trigger.txt检查 public 目录里的文件是不是已经重新生成了(可检查文件大小,生成时间等)。
也可以在 手机 Dropbox 客户端里修改文件 trigger.txt 的内容,public 里的文件的变化。以下是我的构建环境的输出。
ATTRIB : /root/Dropbox/octopress_source/trigger.txt changed, call rake ... ## Generating Site with Jekyll identical source/stylesheets/screen.css Configuration from /root/octopress/_config.yml Building site: source -> public Successfully generated site: source -> public MODIFY : /root/Dropbox/octopress_source/trigger.txt changed, call rake ... ## Generating Site with Jekyll identical source/stylesheets/screen.css Configuration from /root/octopress/_config.yml Building site: source -> public Successfully generated site: source -> public如果测试通过,说明 Dropbox,octowatcher,rake 均运行正常。
至此,构建环境安装配置完毕。
也可以通过 service dropboxd status 和 service octowatcher status 查看服务状态。
在手机上安装 Dropbox 客户端,登录打开 octopress_source 目录,在 _posts 目录中编写文章,写完后修改一下 trigger.txt。然后查看服务器上的文件是不是更新了。
Octopress
的构建环境,配置了 Dropbox 和 octowatcher 服务。并修改 _config.yml 使 destination 属性直接指向了 Apache 的 DocumentRoot 中的一个子目录 /var/www/html/octo。
示例见 http://www.alexcn.com/ 。
文中提到的各个脚本打包下载。
1. Octopress 相关
Source |
|