-
每个系统有一个全局 crontab 文件, 位于 /etc/crontab.
每个用户可以有自己独立的 crontab 文件, 位于 /var/spool/cron/crontabs , 但该文件并不设计为手动编辑的, 正确的方法是使用 crontab -e 来编辑自己的 crontab 文件.
编辑自己用户的 crontab 文件
crontab -e
格式是:
# m h dom mon dow command * * * * * curl http://yiriji.com/admin/cron
-
m, 分钟
-
h, 小时
-
dom, day of month, 日期
-
mon, month, 月份
-
dow, day of week, 星期
和全局的 crontab 不同的是, 没有用户名这一列
如果因书写错误, 则可以到 /var/mail/用户名 文件中查看到错误信息.
Ubuntu中命令/etc/init.d/cron start /etc/init.d/cron stop /etc/init.d/cron restart
Ubuntu中的全局crontab文件示范:# m h dom mon dow user command # 每天每个小时的第17分执行 /etc/cron.hourly 文件下的所有可执行程序或脚本 17 * * * * root cd / && run-parts --report /etc/cron.hourly # 每天6点25分执行 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) # 每个星期天的6点47分执行 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) # 每月1号6点52分执行 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
run-parts 的意思就是执行该文件夹下所有可执行程序或脚本.
-
-
在Apache下设置 Expires Header , 使得图片,CSS, JS得以被浏览器缓存, 以加快页面载入速度.
首先确定apache加载了 mod_expires .
错误示范网上提供在 .htaccess 里面使用 expires 的方法都是:
ExpiresActive On ExpiresDefault A0 ExpiresByType image/gif A2592000 ExpiresByType image/png A2592000 ExpiresByType image/jpg A2592000 ExpiresByType image/jpeg A2592000 ExpiresByType image/ico A2592000 ExpiresByType text/css A2592000 ExpiresByType text/javascript A2592000 ExpiresByType text/html M604800
Note以上设置只会缓存图片, image/* . 但是 实验证明将它们写入 .htaccess 后,会只有image/* , text/css 会被加上 expires 头,而javascript和ico都 不会 被长期缓存.
原因是因为apache的 expiresByType 是根据浏览器请求头中 Accept 来决定的, 浏览器在请求图片的时候会自动在请求头上根据图片类型加上:
Accept: image/png, image/*;q=0.8, */*;q=0.5
而在请求javascript脚本的时候只会发送
Accept: */*
浏览器并不会指明请求类型为 text/javascript , 所以apache的 ExpiresByType 就捕捉不到该类型, 也就不会加上 expires 头.
正确方法因此正确的替代方法是使用 FilesMatch 来替代 ExpiresByType, 例如:
ExpiresActive On ExpiresDefault "access plus 1 year"同样可以加入到 .htaccess 里使用.
-
Git-Diff-Fileset
本工具利用Git等代码仓库生成的 diff (patch)文件, 复制得到一份两次提交之间的差异文件集. (保留目录结果, 文件信息).
该工具意在用于网站程序上线后, 在本地进行了多次代码更新, 需要使用FTP等工具本地将修改的文件集批量上传到服务器, 得到服务器和本地代码同步.
1. 用例
假设你已经将整个应用程序的代码上传到服务器, 然后在本地进行了功能扩展, 修改或增加了一部分文件, 而在本地测试完毕后需要将它们上传到服务器. 在上一次与服务器同步之后, 你在本地进行了一次代码提交. 例如你的 commit log :
commit 2 5b6a52ea652eec20871c6285e00a03bef785edcc Date: Thu Apr 28 12:35:31 2011 +0800 commit 1 e4ef18425c6c49aefa92bb46c847be16b2de019e Date: Thu Apr 28 11:34:05 2011 +0800
commit 1 的文件和服务器是同步的, 你只需要将 commit 2 的修改集上传到服务器.在在commit 2中你一共修改了三个文件:
M /css/style.css M /js/script.js M /index.php
1.1. 生成Patch文件
利用git diff命令生成补丁文件.
git diff master^ > change.diff
1.2. 得到修改集文件拷贝
使用本工具得到一个修改集, 并保留目录结构和基本文件信息(最后修改时间等).
java --jar git-diff.jar -dir /path/to/your/project change.diff
其中dir参数为你的代码跟目录, 即 .git 文件夹的所在; change.diff 为上一步生成的补丁文件.
之后便得到一个拷贝目录, 将包含此次提交的所有修改文件:
/copy/ /copy/index.php /copy/css/style.css /copy/js/script.js
1.3. 使用FTP上传到服务器
你只需使用喜欢的FTP客户端, 把这个目录上传到服务器上相对应的目录即可.
-
Table of Contents
使用HTML缓存可以使得一些对动态要求不高的页面请求更快,也缓解了服务器压力, 比如一些固定的文章页.
而使用Zend Framework构建的应用程序将 非常简单 的可以把服务器输出的内容缓存为html文件, 再之后的请求中, 完全就没有PHP和Zend Frameword什么事了, 只是简单的请求html文件即可, 快速而高效.
但是可惜的是介绍相关内容的资料非常之少, 就连官方手册中也只是对该功能提了一下, 并没有给出完成的用例说明.
这里不仅是介绍如何使用 Zend_Cache 将Zend Framework生成的页面缓存为HTML的方法, 也对其实现方法和原理进行了一些分析, 可不局限与ZF框架, 对PHP生成HTML静态缓存技术有进一步的了解, 同时也研究了ZF是如何利用这些基本缓存技术来实现对整个ZF应用生成的内容进行缓存.
1. PHP生成HTML缓存
首先简单将一些PHP生成HTML缓存的原理, 这有助于我们理解Zend_Cache是如何缓存整个页面的.
首先我们大概都知道 ob_start 函数, 虽然可能很少用过, 但一定见过, 在一般情况下, 我们需要截获PHP输出内容, 一般会使用到这个函数, 例如:
// 开始缓存输出 ob_start(); // 模拟读取数据库之类等耗时操作 $foo = $db->fetchAll("SELECT * FROM {node}"); // 模拟向客户端输出内容 echo $foo; // 因为之前调用了ob_start(), 所以这里并不会立刻输出到客户端 // 而我们可以截获到输出内容 $buffer = ob_get_contents(); // 将输出内容缓存到文件 file_put_contents($buffer, '/tmp/cache.html'); // 将之前的ob缓存释放到客户端 ob_end_clean();而 ob_start 是提供另一种形式的, 就是 ob_start(callback) , 其中 callback 为指定的回调函数名, 该回调函数可能会在如下情况下被调用:
-
调用 ob_flush() , 部分输出内容发送到客户端.
-
调用 ob_clean() , 输出内容发送到客户端.
-
该请求终止时, 输出内容自动发送到客户端.
例子function myCallback($buffer) { file_put_contens($buffer, '/tmp/cache.html'); } ob_start('myCallback'); echo ''; ob_end_flush();这里我们就基本了解了PHP生成HTML的原理, 接下来我们再来看Zend Framework这种具有比较复杂的系统如何来利用该原理实现HTML静态化的.
2. Zend_Cache_Backend_Static
Zend Frameword 中内置的实现HTML静态化的组件就是 Zend_Cache_Backend_Static , 其属于 Zend_Cache 模块. 因此在了解它之前, 你必须了解 Zend_Cache 的原理和使用方法, 这里并不简介, 可以查看手册 Zend_Cache .
Zend_Cache_Backend_Static 作为cache backend, 其必须和cache frontend中的 Zend_Cache_Frontend_Capture 配合使用.
2.1. 内部实现
这里先讲解一下 Zend_Cache_Backend_Static 这个类, 在使用HTML静态化时可以不需要了解这个部分, Zend framework 提供了封住好的 helper 类, 不需要了解实现细节的可以跳过该小节.
Zend_Cache_Backend_Static 的内部实现使用的其实只 Core, File 组合的一个 innerCache , 这里其实也很好理解, 因为它的功能就是将内容输出到文件, 所以就直接使用了 Zend_Cache_Backend_File 作为缓存到文件的功能, 当然这里并不需要去完全理解它, 除非你想要去自己实现 innerCache , 通过设置 Zend_Cache_Backend_Static 的 tag_cache 可以指定自己的 innerCache , 也可以调用 setInnerCache() 来完成.
Zend_Cache_Backend_Static 基本上只有一个外部接口是最值得关注的, 就是 save 方法: boolean save (string $data, string $id, [array $tags = array()], [int $specificLifetime = false])
参数:-
$data , 是需要缓存的内容.
-
$id , 是缓存的ID.
例如调用: $cache->save("bar : data to cache", bin2hex("/bar"));
将会把 "bar : data to cache" 作为文件缓存到 "public/bar.html" (默认设置情况下).
这里也就了解了ZF将会如何去缓存输出到HTML了, 基本上就是通过截获 ob_start 储存起来的输出缓存, 然后把该缓存作为 save 中 $data 参数即可.
3. Zend_Controller_Action_Helper_Cache
该 action helper 则是ZF为我们提供的一个封装好的帮助类, 使用它, 我们基本不需要做任何额外的操作就可以把整个action页缓存成html文件.
既然是 action helper , 那么也就是说ZF提供 Zend_Cache_Backend_Static 这种缓存技术和其他的几个缓存组件并不一定, 它是属于 Controller 级别的缓存, 旨在将某几个 action 页面进行整体缓存, 使用方法也是在 Controller_Action#init 中进行使用的.
这里先讲准备功能, 就是提供少数几个推荐提供给 Zend_Cache_Backend_Static 的参数:
3.1. 步骤1: 配置文件
; Cache - static resources.cachemanager.page.backend.options.public_dir = APPLICATION_PATH "/../public/cached" resources.cachemanager.pagetag.backend.options.cache_dir = APPLICATION_PATH "/data/cache/tags" resources.frontController.params.disableOutputBuffering = true
Note注意大小写, cachemanager 的 m 是小写, 而 frontController 的 C 是大写, 因为这个大小写的原因害我浪费了一天的时间. public_dir一个是 public_dir , 默认的是 ../public , 而有时我们需要把静态文件放置到统一的文件夹中, 如果指定了该文件夹, 并且该文件夹不存在, 就必须确保PHP有 mkdir 此文件夹的权限, 如果该文件夹你创建好了, 那么就必须确保PHP有读写的权限. 我的建议是把这个文件夹创建好, 然后给个比较大的权限 0777 之类的做测试用, 已排除是文件权限导致的静态化失败, 特别是linux系统.
这个文件夹的制定很重要, 手册上推荐的是使用绝对路径(可以使用APPLICATION_PATH). 而且必须保存该文件夹可写, 而且创建HTML文件时就会失败.
Note需要给linux系统的某些用户提醒下就是, PHP生成的HTML文件所有者会是 www-data 之类的apache用户, 而且缓存文件的权限可能只有所有者可读, 你可能会永远看都是空文件夹, 因为你可能没有权限查看该文件夹下的内容 可能ZF已经为你生成了缓存的HTML文件到缓存目录, 而你查看文件夹时会发现总是空, 这是权限问题, 如果你用su用户查看, 就会发现HTML文件已经在那里了. disableOutputBuffering手册上也明确写出了如果要使用该静态缓存功能, 就必须将 disableOutputBuffering 设置为 true , 该选项的功能是关闭 frontController的 outputBufering, 因为默认情况下, 在frontController里面是会使用到 ob_start 的, 而这里我们需要关闭它, 使得我们可以在 Zend_Cache_Backend_Static 中来调用 ob_start(callback) 来缓存所有内容.
3.2. 步骤2: init()
唯一需要做的就是在 init() 内部利用cache helper来制定哪几个action是需要被缓存的即可.
class Node_IndexController extends Zend_Controller_Action { public function init() { $this->_helper->cache(array('index', 'page'), array('allentries')); } public function indexAction() { echo "index action cache"; } public function pageAction() { echo "page action cache"; } }这时你访问 /node/index/index 就会发现你指定的缓存目录下会出现 /node/index/index.html 文件了. 比如你访问 /node 那么就会在缓存目录下直接生成 /node.html , 都是请求路径和缓存目录的路径一一对应的.
Notecache helper是支持 Zend_Layout 的, 生成的内容会包含layout. 3.3. 步骤3: .htaccess
修改 .htaccess 重写规则可以使得你的静态页面路径和不使用静态缓存的url一样, 比如在不使用缓存的情况下, 你的url是 /node/get/ , 而使用缓存后, 假如缓存的HTML文件储存在 public/cached/node/get.html 下, 那么使用重写规则就可以使得用户继续使用 /node/get/ 这个url来访问它, 此时用户访问的就不再是PHP页面, 而是被重写到了 public/cached/node/get.html 这个静态页面. url依然保持一致.
重写规则可以参考手册上的 Zend_Cache_Backend_Static , 这里抄录一份:
AddType application/rss+xml .xml AddType application/atom+xml .xml RewriteEngine On RewriteCond %{REQUEST_URI} feed/rss$ RewriteCond %{DOCUMENT_ROOT}/cached/%{REQUEST_URI}.xml -f RewriteRule .* cached/%{REQUEST_URI}.xml [L,T=application/rss+xml] RewriteCond %{REQUEST_URI} feed/atom$ RewriteCond %{DOCUMENT_ROOT}/cached/%{REQUEST_URI}.xml -f RewriteRule .* cached/%{REQUEST_URI}.xml [L,T=application/atom+xml] RewriteCond %{DOCUMENT_ROOT}/cached/index.html -f RewriteRule ^/*$ cached/index.html [L] RewriteCond %{DOCUMENT_ROOT}/cached/%{REQUEST_URI}.(html|xml|json|opml|svg) -f RewriteRule .* cached/%{REQUEST_URI}.%1 [L] RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L]
我测试出来是此重写规则在某些情况下是会失效的, 比如apache设置的virtualhost里会可能会出现问题(有些配置下), 原因是 %{REQUEST_URI} , 在有时候它会带前置的 / , 比如我请求 http://www.eriji.com/node , 按照重写规则, %{REQUEST_URI} 应该被解析为 node , 而有些设置下它是会被设置为 /node 的, 多一个 / , 使得重写失败, apache将不会重写到我们的缓存文件, 如果你确认的ZF生成了HTML文件到文件系统, 但是因为重定向的问题导致缓存没有被读取, 可以开启 mod_rewrite 的 rewriteLog , 查看具体重定向日志, 检查重写规则是否命中.
3.4. 内部实现
其实在了解了 ob_start(callback) 这个原理后, 我们自己都可以去实现HTML静态化, 但是在ZF里面, 唯一的问题是, 我们什么时候应该开启 ob_start , 而又到什么时候ZF才会把响应的内容(包括layout等)准备完毕, 也就是说什么时候使用 ob_end_lean ,特别是这个时机问题很重要, clean 早了可能缓存里面什么都没有, 也可能在使用了layout的情况下, 缓存里面只有action提供的view内容, 而没有 layout 部分.
我们可以细致的研究下ZF的分发过程, 并且在其中观察 Zend_Controller_Action_Helper_Cache 是怎么来完成这个工作的, 从中可以了解到ZF的分发系统.
首先我们从Controller_Action#init开始追踪, 因此我们在这一步里开始使用了cache helper.
-
Controller_Action#init() , $this→_helper→cache(array(index), ..
-
HelperBroker, 注册cache helper, Zend_Constroller_Action_Helper/Cache#direct
-
Controller_Action#init(), 执行init()剩余部分
-
Controller_Dispatcher(), 一系列分发
-
Controller_Dispatcher_Standard#dispatch, 如果 disableOutputBuffering 没有指定则会调用 ob_start() 我们使用静态缓存的时候就必须关闭它.
-
Controller_Action#dispatch(), action分发
-
Controller_Action_Helper(), 分发到注册的action helper
-
Constoller_Action_Helper_Cache()#preDispatch, 进入cache helper
-
Zend_Cache_Frontend_Capture->start(), 调用 ob_start(array(this, "_flush"))
-
Constoller_Front, 调用所有插件的postDispatch, $this→_plugins→postDispatch($this→_request)
-
Zend_Layout_Controller_Plugin_Layout , layout插件对response→body进行处理, 目前的response→body中只有 action的view内容, 如果使用了layout, 这一步才会把layout的内容添加进来. 准确的说是把action view塞到layout里面去, 然后一起作为response→body.
-
Zend_Cache_Frontend_Captrue#_flush($data) , 得到response→body, 将其作为data参数, 调用 Zend_Cache_Backend_Static#save($data, $id, $tag)
-
Zend_Cache_Backend_Static#save, 调用 file_put_content 将响应内容输出到文件.
-
请求结束.
其中关键的就是 9 和 12 , 都是 Zend_Cache_Frontend_Captrue 进行的操作, 使用的就是 ob_start(callback) 原理, 其中callback函数指定的是自己的 _flush 方法, 而在该方法里, 利用了 Zend_Cache_Backend_Static#save 来将缓存内容生成HTML文件.
-








