自动生成免费 letsencrypt ssl 证书的全自动 nginx 反向代理 docker 镜像

转载, 原文地址: https://github.com/Neilpang/nginx-proxy/wiki
本文是介绍一个 docker 镜像的, 可以全自动实现反向代理, 并自动配置 ssl 证书.

这里主要说两个问题:

  1. 对于只有一个公网 ip 的 docker host, 如果想在其中跑多个 web server 就有问题了, 因为 80 端口只能分配给一个 docker container. 怎么办, 一个好办法就是开一个反向代理. 把 80 端口分配给反向代理, 然后反向代理再根据域名分发给不同的内部 docker container. 看起来很简单对吧, 这没什么. 但是你一旦关闭重启内部的 web server container, 它的内部 ip 可能就会发生改变, 此时你不得不修改反向代理的配置, 并重新加载. 这些工作能不能自动完成 ?
  2. 第二个问题, 反向代理上能不能自动配置 ssl 证书. letsencrypt 不是有免费证书吗?
    很好, 这两个问题的答案都是肯定的. 分三步来说. 不用担心, 非常简单, 本文不会很长, 你会在几分钟只内完成.

1. 先说第一个问题. 自动配置 docker 反向代理.

用 nginx 镜像做一个反向代理, 并且能根据当前 docker host 的 container 的变化, 自动配置反向代理的 ip 和端口.

这个问题其实早就有人解决了, 比如这两个项目:

使用 docker api 可以自动监控 container 变化, 根据模板生成配置文件.

https://github.com/jwilder/docker-gen

作者另外的一个项目, 专门实现了 nginx 的反向代理.

https://github.com/jwilder/nginx-proxy

如果你只需要反向代理, 并不需要自动配置 ssl 的话, 本文你读到这里就可以了.

2. 为 nginx 反向代理自动配置 ssl

为了自动配置 ssl, 我 fork 了上面的项目, 并做了少量修改, 加入了 acme.sh 的支持, 可以实现全自动 配置 ssl 证书.

https://github.com/Neilpang/nginx-proxy

并且已经在 docker hub 上发布了 trusted build:

docker pul neilpang/nginx-proxy

3. 第三步, 快速上手

首先在运行反向代理:

  1. mkdir proxy
  2. cd proxy
  3. docker run \
  4. --rm -it -d \
  5. -p 80:80 \
  6. -p 443:443 \
  7. -v /var/run/docker.sock:/tmp/docker.sock:ro \
  8. -v $(pwd)/certs:/etc/nginx/certs \
  9. -v $(pwd)/acme:/acmecerts \
  10. neilpang/nginx-proxy

稍微解释一下: 运行一个反向代理 并把 80 和 443 端口都分配给它. 并且把 /var/run/docker.sock 传递给 container , 这是 docker api 操作文件.

现在可以运行你的 web server container 了:
先把你的一个域名解析到 docker host ip, 例如: example.com

然后, 我们随便启动一个 webserver:

  1. docker run --rm -itd \
  2. -e VIRTUAL_HOST=example.com \
  3. --name test \
  4. httpd

注意到上面的参数了吗: -e VIRTUAL_HOST=example.com

我们在上一步中运行的 neilpang/nginx-proxy 会自动监控这个 host 上的每一个 container 的变化. 如果发现有 VIRTUAL_HOST 变量, 就会自动配置反向代理.

试试访问你的域名:

http://example.com
现在给这个反向代理配置 ssl:

在此之前,请确保你的域名已经指向了主机 ip, 因为 letsencrypt 证书需要验证域名所有权.

  1. docker kill test
  2. docker run --rm -itd \
  3. -e VIRTUAL_HOST=example.com \
  4. -e ENABLE_ACME=true \
  5. --name test \
  6. httpd

注意到不同了吗, 仅仅多了一个变量: ENABLE_ACME=true

大概几十秒之后, ssl 证书就会自动配置成功了.

访问试试:

https://example.com
注意, 这个证书是自动配置的, 今后会自动更新, 让你完全忘了它的存在.

有多个域名绑定: 用逗号分隔.

  1. docker kill test
  2. docker run --rm -it -d \
  3. -e VIRTUAL_HOST=example.com,www.example.com \
  4. -e ENABLE_ACME=true \
  5. --name test \
  6. httpd

另外, 这个镜像还有一个好处就是已经配置了从 http 跳转到 https, 并且自动启用 http 2.0

反代 非 80 的自定义端口:
加上: VIRTUAL_PORT=8080 即可

  1. docker run --rm -itd \
  2. -e VIRTUAL_HOST=example.com,www.example.com \
  3. -e ENABLE_ACME=true \
  4. -e VIRTUAL_PORT=8080 \
  5. --name test \
  6. httpd

比如搭建gogs 服务器:

  1. docker run -itd --restart always \
  2. --name gogs \
  3. -e VIRTUAL_HOST=git.ngapp.net \
  4. -e ENABLE_ACME=true \
  5. -e VIRTUAL_PORT=3000 \
  6. -v /data/gogs:/data \
  7. gogs/gogs

原文链接: https://github.com/Neilpang/nginx-proxy/wiki

希望能帮到更多人,节约你的时间和精力.

欢迎大家转载 请保留链接.

欢迎 star:

https://github.com/Neilpang/nginx-proxy

基于 Composer 的 PHP 模块化开发

转载, 文章原始地址: https://zhuanlan.zhihu.com/p/27943241
订阅号:假装我会写代码

这个话题之前是在微博公司内部做的技术分享,这里拿出来分享给大家。

基于 GitHub 或者其它平台托管的开源项目的引入大家应该都已经非常熟悉了,但是公司内部项目的模块化应该怎么做呢?这或许是不少朋友头疼的问题。

我们先聊聊 PHP 模块化开发演进的过程,在没有 GitHub 之前,我们大家获取与分享代码的方式主要是博客,国内的 CSDN 或者博客园还有很多很多,大家都是从文章内复制到自己项目里面使用。现在看起来真的是相当原始粗暴,但是那个时代也没有太多可选的方案。导致的现象就是一段代码在 N 个项目里出现,可能见得最多的就是获取客户端 IP 的那几行了,在互联网上不止出现了几万遍。现在很多项目里都还是这段:

是不是很熟悉?

这种引入代码的方式有很多弊端:比如不安全,因为很多人是直接复制粘贴就用上了,根本没花时间去考证它是否真的是安全的。另外一个问题就是不同步,你今天在别人那里复制过来就用上了,后来作者发现了 bug 并修复更新了文章也不会通知你,你也不可能记得这段代码来自哪里去检查更新。

在没有 Composer 之前我们是如何引入代码的呢?除了上面说的复制粘贴以外,在 PHP 中还有 pear,不过自从用过两次我就再也不用它了,一种说不出来的感觉。

不信你可以找一些旧的项目看看,在没有 Composer 之前的项目中,你会发现大量的重复代码,以及各种花样的组织格式,各种规范的写法。这也是 Composer 诞生的原因之一。

Composer 给我们带来了诸多的好处:

  • 模块化,降低代码重用成本
  • 统一的第三方代码组织方式
  • 更科学的版本更新
    这三个是比较重要的特征了,基于 GitHub 的共享代码方式解决了传统引入方式带来了各种问题。

我们先来了解一点 Composer 基础。

Composer 的实现结构相对比较简单,http://Packagist.org 是 Composer 官方数据源,它的数据基于 GitHub 等代码托管平台,你在本地使用 Composer 命令行工具,基于 http://Packagist.org 的数据信息安装与更新依赖。
本地安装 Composer 非常简单,主要有以下几种方式:

新手同学需要注意的是,这里一定要确定 composer 安装目录在环境变量 $PATH 内才能全局使用 composer 命令。

那接下来我们聊一下如何创建一个 Composer 包。

步骤很简单,创建目录,然后在目录内使用命令 composer init 按照提示完成包的初始化。

接着就是完成你的代码编写,然后在 composer.json 文件配置你的引入方式等信息。
然后我们如何对已经写好的代码进行测试呢?

我们需要在其它任何地方建立一个测试项目(不要在刚才创建的包目录就可以),比如这里我们创建一个叫 ‘my-package-test’ 的目录,然后在目录里 composer init 完成项目初始化。接着就是声明项目依赖,我们这里要依赖的就是刚才建立好的包,由于我们的包还没有发布到 packagist,所以是无法直接 composer require 来安装的,我们需要告诉 composer 从哪里加载我们的包信息:

  1. $ composer config repositories.foo path /Users/overtrue/www/foo/bar

我们通过这个命令在 composer.json 中 repositories 区块添加了一个项目源。

然后我们添加包依赖:

  1. $ composer require foo/bar:dev-master -vvv

这样就完成了包的安装,你会发现这样的安装方式它只是创建了一个软链接到包目录,所以,你在测试的时候就可以直接在 vendor/foo/bar 下修改代码,这样就加快了你的开发速度。

更多细节这里你就自己去研究了,我们来看看 composer.json 文件:

我们最需要关心的就是图里上面的三个部分了,包名、依赖、以及自动加载,是必不可少的部分。

刚才我们提到了包的安装,安装依赖包的方式主要有以下两种:

手动方式是不太推荐的,容易写错,比如后面多一个逗号之类的,不过你可以写完以后使用以下命令来验证:

  1. $ composer validate

更新依赖就非常简单了:

虽然在上一篇文章我们已经讲了语义化版本,这里再提一次:

我们在依赖一个包的时候,很多同学对于依赖的版本一直处于蒙逼状态,那看完下一页你就恍然大悟了,首先是两个符号:”~” 与 “^”

接着是版本号的范围的各种写法:

还有包含稳定性的标识:

这里需要说一下生产环境最重要也一直是好多同学不清楚的一个东西:版本锁定,很多人在纠结,要不要把 composer.lock 上传到代码库啊。我可以给你一个特别简单的判断方法:

如果你的代码是一个项目,就上传,如果是一个工具包,给大家用的,就别上传。

在已经存在 composer.lock 的目录执行 composer install 的时候,是不会分析包依赖的,它只是按 composer.lock 中描述的下载地址直接下载,所以会快很多,而且版本号是具体的。那怕包已经发了新版,只要 composer.lock 没动过,它就会按 composer.lock 里的版本来安装。composer update 时会更新 composer.lock,所以不要乱用 composer update。

包开发好了怎么发布?开源的方式是这样的:

最后一句请酌情考虑。

另外一种发布方式是闭源,公司内部用的包,上传到 GitLab 或者其它私有的代码托管平台,有两种玩法:

  1. 最容易的玩法,在 composer.json 中添加 repositories 直接用 vcs 指定代码库地址
    这样做有一个缺点,当你的包很多的时候,你全都得在 composer.json 中加上才行。

  2. 自已架设 Packagist 类似的服务,Packagist 官方提供了两款: toran,收费,开源方案是 Satis,不过它偏手动一些,自己酌情选择即可。

私有包有一个点需要注意:授权,私有包肯定都是需要授权才能访问的,这里由于方案不太通用,大家根据自己的场景来解决就好了。

另外,有一些痛点不晓得啥时候能够解决:

好在 Laravel China 已经为了我提供了国内目前最稳定最好用的镜像源,Composer 中文镜像 / Packagist 中国全量镜像正式发布!

最后总结一下:

  在 PHP 现代开发中,Composer 已经是离不开的东西了,它的确加快了我们的开发速度节省了开发成本,如果你还在纠结用不用 Composer,那你真得反思一下了。

  本文标题是模块化开发,内容主要介绍了包的创建与测试,以及公有包与私有包的发布方案。但是无法帮你解决,如何拆分项目这类问题,这得基于你的长期经验积累,但是有一些经验可以分享一下:

  • 不要过度设计,很多自以为很 NB 我不把学到的东西用上就是不爽的同学,上来就分库分表,uuid 做主键之类,项目运营了好几年一个表还没到100万条记录,也是够厉害的。

  • 不要过早设计,真正 NB 的架构是演进而来的,不是前期设计出来的,当然不是说完全不需要设计哈,恰当的根据实际情况来就好,不要立项就把“千万”、“亿级”、“百亿” 这些单位挂在嘴边,也许到你项目倒闭那天你都没到过任何一个量级。随着项目逐渐改进即可。

  • 优先关注成本,很多同学以为是性能,No! 技术团队真正的成本是人力,所以开发效率才是优先需要关注的。上次文章在发在知乎有人就强制把我的“不要首先关注性能”解读成了“性能不重要”,也是够厉害的,语文也许跟养殖场动物学的。数学正常一点的人都会算,一台服务器多少钱?一个技术员工多少钱?服务器你花 20 万是永久资产,一个员工 20 万呢?半年工资?一年工资?

docker的web管理工具

海鸥

Docker Pulls
GoDoc
Gitter

简介

Seagull 友好的docker Web界面管理工具

  • 易于安装和卸载在Docker容器
  • 单击开始/停止/删除容器和镜像
  • 超快速(小于10ms)的搜索和过滤
  • 支持多主机管理和监控
  • 国际化主要包括英语、汉语、德语和法语

更多信息, 请到 dockerseagull.com, 观看 三分钟视频官方的幻灯片.

github地址

点击跳转: https://github.com/tobegit3hub/seagull

安装

  1. docker run -d -p 10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull

或运行 docker-compose up -d.

截图

多主机

Seagull支持监控多台服务器。确保你开始Docker守护这样。

  1. docker -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock -api-enable-cors=true -d

参与

Seagull is written in Go with tools like Docker, Beego, AngularJS, Bootstrap and JQuery.

  1. Install golang and setup $GOPATH
  2. go get github.com/astaxie/beego
  3. go get github.com/tobegit3hub/seagull
  4. go build seagull.go
  5. sudo ./seagull

More detail in seagull-design-and-implement and we have excellent documents in docs.

提醒

The issue #2 每个人都可以在IP和端口海鸥接触访问您的码头工人守护。为了安全,你可以绑定到本地主机的访问限制。

  1. docker run -d -p 127.0.0.1:10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull

类似的Docker项目

现在有很多类似的项目提供了Web界面来监控Docker。海鸥就是受他们影响并且期望做得比他们更好。

我想把这些项目都介绍给你们,任何人都可以根据他们所需要的进行选择。

Dockerui

这是它的Github主页,https://github.com/crosbymichael/dockerui.

你可以发现海鸥的UI是有点像Dockerui。因为我们都使用了Bootstrap和AngularJS作为前端框架。它是一个很好的项目并且在Github上有差不多2000个关注。

海鸥从Dockerui中学习了很多,包括使用JQuery.Gritter作为网站通知。但Dockerui的界面不够简洁,而且它没有考虑到国际化的需求,而我们考虑到了。我们愿意为全世界的开发者多做些事情。Dockerui还没有实现搜索功能而海鸥则很擅长这点。

Dockerui和海鸥是同类型产品,用于监控Docker。你没必要同时使用他们。而我们的目标就是用一个更友好、更实用的UI满足用户,并且取代Dockerui。

Zdocker

这是它的Github主页,https://github.com/love320/Zdocker.

Zdocker做了同类的事情来监控Docker镜像和容器。但它是使用Java实现的,而且没有提供Docker镜像,而且人们很难使用和学习。

这只能算是个人项目,我并不建议你去使用。因为目前为止我也不知道该怎样去运行它。

Shipyard

这是它的Github主页,https://github.com/shipyard/shipyard.

Shipyard设计来管理一个Docker集群。你必须输入服务器的SSH认证代码才能部署Shipyard引擎。然后你就可以通过命令行或者Web界面在你管理的服务器上部署容器了。

它和海鸥是非常不同的,因为海鸥仅仅是监控Docker而不会要求更多的权限。因此你可以使用Shipyard作为管理系统,同时使用海鸥来监控Docker。

CAdvisor

这是它的Github主页,https://github.com/google/cadvisor.

CAdvisor来自于Google,它主要是为了分析容器的资源。你可以使用它来监控你的容器占用CPU或者内存的历史情况。

然后,你不能用CAdivsor来管理你的镜像和容器。

Docker Registry Web

这是它的Github主页,https://github.com/atc-/docker-registry-web.

这是为Docker参与设计的Web界面。它的UI展示不错但你必须手动添加私有仓库地址。它用了Cookies来存储这个地址所以每次你运行时都要重新添加。

当我尝试去搜索Docker镜像时程序崩溃了。当我尝试去或者镜像详细信息的时候它显示“方法未授权”。

我希望他们可以在我们添加私有仓库时就默认添加Docker官方仓库。但我不太可能因为http://registry.hub.docker.com不支持CORS。

Docker Registry UI

这是它的Github主页,https://github.com/worksap-ate/docker-registry-ui.

这也是为Docker仓库设计的Web界面。它能用但是UI不是很好。

Docker Register Frontend

这是它的Github主页,https://github.com/kwk/docker-registry-frontend.

这几乎是跟Docker-registry-web和Docker-registry-ui是一样的东西。

Ubuntu 的 https协议 和 反向代理

下面假设你的域名是 git.ngapp.net , 配置服务器用 Ubuntu + Apache

ssl免费证书申请:

  1. 沃通提供的免费ssl证书: https://buy.wosign.com/free/
  2. 解压复制apache需要的文件到 /etc/apache2/ssl 目录

配置Apache

增加配置 /etc/apache2/apache2.conf
  1. ServiceName localhost
开启需要的模块
  1. a2enmod ssl
  2. a2enmod proxy
  3. a2enmod proxy_http
添加配置 /etc/apache2/sites-enabled/git.ngapp.net.conf
  1. <VirtualHost *:443>
  2. SSLEngine On
  3. SSLCertificateFile /etc/apache2/ssl/git.ngapp.net.crt
  4. SSLCertificateKeyFile /etc/apache2/ssl/git.ngapp.net.key
  5. SSLCertificateChainFile /etc/apache2/ssl/root_bundle.crt
  6. ServerName git.ngapp.net
  7. ServerAdmin zhaishuaigan@qq.com
  8. ProxyPreserveHost On
  9. ProxyRequests Off
  10. <Proxy *>
  11. AddDefaultCharset off
  12. Order deny,allow
  13. Allow from all
  14. </Proxy>
  15. ProxyPass / http://localhost:3000/
  16. ProxyPassReverse / http://localhost:3000/
  17. </VirtualHost>
  18. <VirtualHost *:80>
  19. ServerName git.ngapp.net
  20. ServerAdmin zhaishuaigan@qq.com
  21. RewriteEngine on
  22. RewriteCond %{SERVER_PORT} !^443$
  23. RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
  24. </VirtualHost>

git服务器搭建

如何严格限制session在30分钟后过期

  1. 设置客户端cookie的lifetime为30分钟;
  2. 设置session的最大存活周期也为30分钟;
  3. 为每个session值加入时间戳,然后在程序调用时进行判断;

  至于为什么,我们首先来了解下php中session的基本原理:

  PHP中的session有效期默认是1440秒(24分钟),也就是说,客户端超过24分钟没有刷新,当前session就会失效。当然如果用户关闭了浏览器,会话也就结束了,Session自然也不存在了!

  大家知道,Session储存在服务器端,根据客户端提供的SessionID来得到这个用户的文件,然后读取文件,取得变量的值,SessionID可以使用客户端的Cookie或者Http1.1协议的Query_String(就是访问的URL的“?”后面的部分)来传送给服务器,然后服务器读取Session的目录……

  要控制Session的生命周期,首先我们需要了解一下php.ini关于Session的相关设置(打开php.ini文件,在“[Session]”部分):

  1. session.use_cookies:默认的值是“1”,代表SessionID使用Cookie来传递,反之就是使用Query_String来传递;
  2. session.name:这个就是SessionID储存的变量名称,可能是Cookie,也可能是Query_String来传递,默认值是“PHPSESSID”;
  3. session.cookie_lifetime:这个代表SessionID在客户端Cookie储存的时间,默认是0,代表浏览器一关闭SessionID就作废……就是因为这个所以Session不能永久使用!
  4. session.gc_maxlifetime:这个是Session数据在服务器端储存的时间,如果超过这个时间,那么Session数据就自动删除!

  还有很多的设置,不过和本文相关的就是这些了,下面开始讲如何设置Session的存活周期。

  前面说过,服务器通过SessionID来读取Session的数据,但是一般浏览器传送的SessionID在浏览器关闭后就没有了,那么我们只需要人为的设置SessionID并且保存下来,不就可以……

  如果你拥有服务器的操作权限,那么设置这个非常非常的简单,只是需要进行如下的步骤:

  1. 把“session.use_cookies”设置为1,使用Cookie来储存SessionID,不过默认就是1,一般不用修改;
  2. 把“session.cookie_lifetime”改为你需要设置的时间(比如一个小时,就可以设置为3600,以秒为单位);
  3. 把“session.gc_maxlifetime”设置为和“session.cookie_lifetime”一样的时间;

  在PHP的文档中明确指出,设定session有效期的参数是session.gc_maxlifetime。可以在php.ini文件中,或者通过ini_set()函数来修改这一参数。问题在于,经过多次测试,修改这个参数基本不起作用,session有效期仍然保持24分钟的默认值。

  由于PHP的工作机制,它并没有一个daemon线程,来定时地扫描session信息并判断其是否失效。当一个有效请求发生时,PHP会根据全局变量session.gc_probability/session.gc_divisor(同样可以通过php.ini或者ini_set()函数来修改)的值,来决定是否启动一个GC(Garbage Collector)。

  默认情况下,session.gc_probability = 1,session.gc_divisor =100,也就是说有1%的可能性会启动GC。GC的工作,就是扫描所有的session信息,用当前时间减去session的最后修改时间(modified date),同session.gc_maxlifetime参数进行比较,如果生存时间已经超过gc_maxlifetime,就把该session删除。

  到此为止,工作一切正常。那为什么会发生gc_maxlifetime无效的情况呢?

  在默认情况下,session信息会以文本文件的形式,被保存在系统的临时文件目录中。在Linux下,这一路径通常为\tmp,在 Windows下通常为C:\Windows\Temp。当服务器上有多个PHP应用时,它们会把自己的session文件都保存在同一个目录中。同样地,这些PHP应用也会按一定机率启动GC,扫描所有的session文件。

  问题在于,GC在工作时,并不会区分不同站点的session。举例言之,站点A的gc_maxlifetime设置为2小时,站点B的 gc_maxlifetime设置为默认的24分钟。当站点B的GC启动时,它会扫描公用的临时文件目录,把所有超过24分钟的session文件全部删除掉,而不管它们来自于站点A或B。这样,站点A的gc_maxlifetime设置就形同虚设了。

  找到问题所在,解决起来就很简单了。修改session.save_path参数,或者使用session_save_path()函数,把保存session的目录指向一个专用的目录,gc_maxlifetime参数工作正常了。

  还有一个问题就是,gc_maxlifetime只能保证session生存的最短时间,并不能够保存在超过这一时间之后session信息立即会得到删除。因为GC是按机率启动的,可能在某一个长时间内都没有被启动,那么大量的session在超过gc_maxlifetime以后仍然会有效。

Netbeans配置远程调试ubuntu apache2 php5-xdebug

此配置方法适用于在虚拟机中搭建服务器环境, 在windows中编码的方式

1. 安装php5-xdebug

  1. sudo apt-get install php5-xdebug

2. 配置php.ini, 在最后添加xdebug配置项

  1. [xdebug]
  2. zend_extension="/usr/lib/php5/20131226/xdebug.so"
  3. xdebug.idekey="netbeans-xdebug"
  4. xdebug.remote_host=192.168.100.103
  5. xdebug.remote_connect_back=1
  6. xdebug.remote_port=9000
  7. xdebug.profiler_enable=on
  8. xdebug.remote_enable=on
  9. xdebug.remote_handle=dbgp

说明

  1. zend_extension="/usr/lib/php5/20131226/xdebug.so" # 这里根据php的版本不同, 日期路径也不一样
  2. xdebug.remote_host=192.168.100.103 # 主机的地址
  3. xdebug.remote_port=9000 # 主机netbeans的监听端口(工具 > 选项 > php > 调试 > 调试端口)

php调用系统shell命令自动更新线上网站代码为git版本库最新版

我们开发网站经常使用git最为代码版本库管理功能, git可以方便多人合作和代码历史记录的保存, 很方便, 于是有很多人就直接把git版本库的代码直接部署到线上, 每次更新就用git pull 去更新网站的代码, 只是每次更新代码都需要ssh到服务器上, 很麻烦, 想到php可以执行系统命令, 就想到了用网页更新线上代码, 具体往下看

准备

  1. 你的网站是php写的
  2. 你网站的代码使用的是git clone的代码, 更新代码使用的是git pull方式

自动更新php文件

1 . 在网站根目录下新建 /update.php, 并写入下面的代码, 可以把DIR修改成网站所在目录, 如果是当前目录, 可以不修改.

  1. <?php
  2. chdir(__DIR__);
  3. echo '<pre>';
  4. echo shell_exec('/usr/bin/git pull 2>&1');

2 . 然后修改网站目录中的文件所有文件的权限为 0777
3 . 把 .git/config 文件的远程提交地址中加上帐号信息 https://username:password@git.xxx.com/xxxxx
4 . 然后就可以访问 http://xxx.com/update.php 来更新网站代码了

注意: 如果你的网站根目录是源码根目录, 要禁止http访问.git目录, 因为这里保存了你的git帐号

linux自动压缩apache日志的计划任务脚本

上线后的网站, apache的日志每天都会增长很多, 有时一天就是几个G, 要么关闭日志, 要么压缩保存, 这里提供一个定时压缩的脚本, 每天

步骤

  1. 创建备份压缩脚本
  2. 创建计划任务

1. 创建备份压缩脚本

在服务器上创建一个shell脚本文件, 写入以下内容
  1. now_date=`date -d yesterday +%Y_%m_%d`
  2. /usr/bin/gzip -c 日志文件路径/access.log > 压缩后的路径/access.log_${now_date}.gz
  3. echo "" > 日志文件路径/access.log
  4. /usr/bin/gzip -c 错误日志文件路径/error.log > 错误日志文件路径/error.log_${now_date}.gz
  5. echo "" > 错误日志文件路径/error.log
实例: /data/wwwlog/gzip_log.cron
  1. now_date=`date -d yesterday +%Y_%m_%d`
  2. /usr/bin/gzip -c /data/wwwlog/access.log > /data/wwwlog/access.log_${now_date}.gz
  3. echo "" > /data/wwwlog/access.log
  4. /usr/bin/gzip -c /data/wwwlog/error.log > /data/wwwlog/error.log_${now_date}.gz
  5. echo "" > /data/wwwlog/error.log

2. 创建计划任务

  1. 在命令行输入 crontab -e 调出计划任务配置文件
  2. 写入配置 10 0 * * * sh /data/wwwlog/gzip_log.cron
  3. esc :wq 回车保存

这样就可以在每天晚上 12点压缩日志了

php内置服务器使用方法

1 启动Web服务器

  1. $ cd ~/public_html
  2. $ php -S localhost:8000

终端输出信息:

  1. PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011
  2. Listening on localhost:8000
  3. Document root is /home/me/public_html
  4. Press Ctrl-C to quit

当请求了 http://localhost:8000/http://localhost:8000/myscript.html 地址后,终端输出类似如下的信息:

  1. PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011
  2. Listening on localhost:8000
  3. Document root is /home/me/public_html
  4. Press Ctrl-C to quit.
  5. [Thu Jul 21 10:48:48 2011] ::1:39144 GET /favicon.ico - Request read
  6. [Thu Jul 21 10:48:50 2011] ::1:39146 GET / - Request read
  7. [Thu Jul 21 10:48:50 2011] ::1:39147 GET /favicon.ico - Request read
  8. [Thu Jul 21 10:48:52 2011] ::1:39148 GET /myscript.html - Request read
  9. [Thu Jul 21 10:48:52 2011] ::1:39149 GET /favicon.ico - Request read

2 启动web服务器时指定文档的根目录

  1. $ cd ~/public_html
  2. $ php -S localhost:8000 -t foo/

终端显示信息:

  1. PHP 5.4.0 Development Server started at Thu Jul 21 10:50:26 2011
  2. Listening on localhost:8000
  3. Document root is /home/me/public_html/foo
  4. Press Ctrl-C to quit

如果你在启动命令行后面附加一个php脚本文件,那这个文件将会被当成一个“路由器”脚本。这个脚本将负责所有的HTTP请求,如果这个脚本执行时返回FALSE,则被请求的资源会正常的返回。如果不是FALSE,浏览里显示的将会是这个脚本产生的内容。

3 使用路由器脚本

在这个例子中,对图片的请求会返回相应的图片,但对HTML文件的请求会显示“Welcome to PHP”:

  1. <?php
  2. // router.php
  3. if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
  4. return false; // serve the requested resource as-is.
  5. } else {
  6. echo "<p>Welcome to PHP</p>";
  7. }
  8. ?>

执行:

  1. $ php -S localhost:8000 router.php

4 判断是否是在使用内置web服务器

通过程序判断来调整同一个PHP路由器脚本在内置Web服务器中和在生产服务器中的不同行为:

  1. <?php
  2. // router.php
  3. if (php_sapi_name() == 'cli-server') {
  4. /* route static assets and return false */
  5. }
  6. /* go on with normal index.php operations */
  7. ?>

执行:

  1. $ php -S localhost:8000 router.php

这个内置的web服务器能识别一些标准的MIME类型资源,它们的扩展有:.css, .gif, .htm, .html, .jpe, .jpeg, .jpg, .js, .png, .svg, and .txt。对.htm 和 .svg 扩展到支持是在PHP 5.4.4之后才支持的。

5 处理不支持的文件类型

如果你希望这个Web服务器能够正确的处理不被支持的MIME文件类型,这样做:

  1. <?php
  2. // router.php
  3. $path = pathinfo($_SERVER["SCRIPT_FILENAME"]);
  4. if ($path["extension"] == "ogg") {
  5. header("Content-Type: video/ogg");
  6. readfile($_SERVER["SCRIPT_FILENAME"]);
  7. }
  8. else {
  9. return FALSE;
  10. }
  11. ?>

执行:

  1. $ php -S localhost:8000 router.php

如果你希望能远程的访问这个内置的web服务器,你的启动命令需要改成下面这样:

6 远程访问这个内置Web服务器

  1. $ php -S 0.0.0.0:8000

这样你就可以通过 8000 端口远程的访问这个内置的web服务器了。