git小型团队,协作使用约定

#git分支约定

master = 正式版本
develop = 开发版本

#git定型版本tag

当每个develop版本合并至master分支以后,打git tag 1.1.2版本标签,便于版本细节变化操作的跟踪.

#bug相关

当正式版本产生bug的时候,可能需要修改代码,为了后期便于维护,请根据以下约定进行操作.

#本地场景操作->确认至本地master版本

git checkout master

#更新本地分支

git pull origin master

#创建本地bug分支版本

git branch bug#1.1.2

#修复以后的操作

git checkout master
``

#合并分支

git merge bug#1.1.2


#写入日记

git commit -m “日记,写入本地合并的操作相关信息”


#打标签

git tag -a 1.1.2 -m “Release version 1.1.2”


#详解 git tag命令

-a 1.1.2 是增加名为1.1.2的标签
-m 后面跟着的是标签的注释


#提交标签到远程服务器上

git push origin master
git push origin --tags
–tags参数表示提交所有tag至服务器端,普通的git push origin master操作不会推送标签到服务器端。


#删除标签的命令

git tag -d  1.1.2


#删除远端服务器的标签

git push origin :refs/tags/1.1.2
```

php geohash附近算法和使用类

原理google

 

实现类

<?php

class Geohash {

    private $bitss = array(16, 8, 4, 2, 1);
    private $neighbors = array();
    private $borders = array();

    private $coding = "0123456789bcdefghjkmnpqrstuvwxyz";
    private $codingMap = array();

    /**
     * 实例化数据
     * Geohash constructor.
     */
    public function __construct()
    {
        $this->neighbors['right']['even'] = 'bc01fg45238967deuvhjyznpkmstqrwx';
        $this->neighbors['left']['even'] = '238967debc01fg45kmstqrwxuvhjyznp';
        $this->neighbors['top']['even'] = 'p0r21436x8zb9dcf5h7kjnmqesgutwvy';
        $this->neighbors['bottom']['even'] = '14365h7k9dcfesgujnmqp0r2twvyx8zb';

        $this->borders['right']['even'] = 'bcfguvyz';
        $this->borders['left']['even'] = '0145hjnp';
        $this->borders['top']['even'] = 'prxz';
        $this->borders['bottom']['even'] = '028b';

        $this->neighbors['bottom']['odd'] = $this->neighbors['left']['even'];
        $this->neighbors['top']['odd'] = $this->neighbors['right']['even'];
        $this->neighbors['left']['odd'] = $this->neighbors['bottom']['even'];
        $this->neighbors['right']['odd'] = $this->neighbors['top']['even'];

        $this->borders['bottom']['odd'] = $this->borders['left']['even'];
        $this->borders['top']['odd'] = $this->borders['right']['even'];
        $this->borders['left']['odd'] = $this->borders['bottom']['even'];
        $this->borders['right']['odd'] = $this->borders['top']['even'];

        //build map from encoding char to 0 padded bitfield
        for($i=0; $i<32; $i++)
        {
            $this->codingMap[substr($this->coding, $i, 1)] = str_pad(decbin($i), 5, "0", STR_PAD_LEFT);
        }

    }

    /**
     * 解密
     * @param 纬度,经度 lat,long in it
     */
    public function decode($hash)
    {

        //decode hash into binary string
        $binary = "";
        $hl = strlen($hash);
        for ($i=0; $i<$hl; $i++) {

            $binary .= $this->codingMap[substr($hash, $i, 1)];
        }

        //split the binary into lat and log binary strings
        $bl = strlen($binary);
        $blat = "";
        $blong = "";
        for ($i=0; $i<$bl; $i++) {

            if ($i%2)
                $blat=$blat.substr($binary, $i, 1);
            else
                $blong=$blong.substr($binary, $i, 1);

        }

        //now concert to decimal
        $lat = $this->binDecode($blat, -90, 90);
        $long = $this->binDecode($blong, -180, 180);

        //figure out how precise the bit count makes this calculation
        $latErr = $this->calcError(strlen($blat), -90, 90);
        $longErr = $this->calcError(strlen($blong), -180, 180);

        //how many decimal places should we use? There's a little art to
        //this to ensure I get the same roundings as geohash.org
        $latPlaces = max(1, -round(log10($latErr))) - 1;
        $longPlaces = max(1, -round(log10($longErr))) - 1;

        //round it
        $lat = round($lat, $latPlaces);
        $long = round($long, $longPlaces);

        return array($lat, $long);
    }


    private function calculateAdjacent($srcHash, $dir) {

        $srcHash = strtolower($srcHash);
        $lastChr = $srcHash[strlen($srcHash) - 1];
        $type = (strlen($srcHash) % 2) ? 'odd' : 'even';
        $base = substr($srcHash, 0, strlen($srcHash) - 1);

        if (strpos($this->borders[$dir][$type], $lastChr) !== false) {

            $base = $this->calculateAdjacent($base, $dir);
        }

        return $base . $this->coding[strpos($this->neighbors[$dir][$type], $lastChr)];
    }


    /**
     * 获取相对区域的8个位置
     * @param $srcHash
     * @return mixed
     */
    public function neighbors($srcHash)
    {

        $geohashPrefix = substr($srcHash, 0, strlen($srcHash) - 1);

        $neighbors['top'] = $this->calculateAdjacent($srcHash, 'top');
        $neighbors['bottom'] = $this->calculateAdjacent($srcHash, 'bottom');
        $neighbors['right'] = $this->calculateAdjacent($srcHash, 'right');
        $neighbors['left'] = $this->calculateAdjacent($srcHash, 'left');

        $neighbors['topleft'] = $this->calculateAdjacent($neighbors['left'], 'top');
        $neighbors['topright'] = $this->calculateAdjacent($neighbors['right'], 'top');
        $neighbors['bottomright'] = $this->calculateAdjacent($neighbors['right'], 'bottom');
        $neighbors['bottomleft'] = $this->calculateAdjacent($neighbors['left'], 'bottom');

        return $neighbors;
    }

    /**
     * 经纬度加密
     * @param $lat 纬度
     * @param $long 经度
     * @return string
     */
    public function encode($lat, $long)
    {

        //how many bits does latitude need?
        $plat = $this->precision($lat);
        $latbits = 1;
        $err = 45;
        while($err > $plat) {

            $latbits++;
            $err /= 2;
        }

        //how many bits does longitude need?
        $plong = $this->precision($long);
        $longbits = 1;
        $err = 90;
        while($err > $plong) {

            $longbits++;
            $err /= 2;
        }

        //bit counts need to be equal
        $bits = max($latbits, $longbits);

        //as the hash create bits in groups of 5, lets not
        //waste any bits - lets bulk it up to a multiple of 5
        //and favour the longitude for any odd bits
        $longbits = $bits;
        $latbits = $bits;
        $addlong = 1;
        while (($longbits + $latbits) % 5 != 0) {

            $longbits += $addlong;
            $latbits += !$addlong;
            $addlong = !$addlong;
        }


        //encode each as binary string
        $blat = $this->binEncode($lat, -90, 90, $latbits);
        $blong = $this->binEncode($long, -180, 180, $longbits);

        //merge lat and long together
        $binary = "";
        $uselong = 1;
        while (strlen($blat) + strlen($blong)) {

            if ($uselong) {

                $binary = $binary.substr($blong, 0, 1);
                $blong = substr($blong, 1);

            } else {

                $binary = $binary.substr($blat, 0, 1);
                $blat = substr($blat, 1);
            }

            $uselong = !$uselong;
        }

        //convert binary string to hash
        $hash = "";
        for ($i=0; $i<strlen($binary); $i+=5) {

            $n = bindec(substr($binary, $i, 5));
            $hash = $hash.$this->coding[$n];
        }

        return $hash;
    }

    /**
     * What's the maximum error for $bits bits covering a range $min to $max
     */
    private function calcError($bits, $min, $max)
    {

        $err = ($max - $min) / 2;
        while ($bits--)
            $err /= 2;
        return $err;
    }

    /*
    * returns precision of number
    * precision of 42 is 0.5
    * precision of 42.4 is 0.05
    * precision of 42.41 is 0.005 etc
    *
    * Author: Bruce Chen (weibo: @一个开发者)
    */
    private function precision($number)
    {

        $precision = 0;
        $pt = strpos($number,'.');
        if ($pt !== false) {

            $precision = -(strlen($number) - $pt - 1);
        }

        return pow(10, $precision) / 2;
    }


    /**
     * create binary encoding of number as detailed in http://en.wikipedia.org/wiki/Geohash#Example
     * removing the tail recursion is left an exercise for the reader
     *
     * Author: Bruce Chen (weibo: @一个开发者)
     */
    private function binEncode($number, $min, $max, $bitcount)
    {

        if ($bitcount == 0)
        {
            return '';
        }

        #echo "$bitcount: $min $max<br>";

        //this is our mid point - we will produce a bit to say
        //whether $number is above or below this mid point
        $mid = ($min + $max) / 2;
        if ($number > $mid)
            return "1" . $this->binEncode($number, $mid, $max, $bitcount - 1);
        else
            return "0" . $this->binEncode($number, $min, $mid, $bitcount - 1);
    }


    /**
     * decodes binary encoding of number as detailed in http://en.wikipedia.org/wiki/Geohash#Example
     * removing the tail recursion is left an exercise for the reader
     * Author: Bruce Chen (weibo: @一个开发者)
     */
    private function binDecode($binary, $min, $max)
    {

        $mid = ($min + $max) / 2;

        if (strlen($binary) == 0)
        {
            return $mid;
        }

        $bit = substr($binary, 0, 1);
        $binary = substr($binary, 1);

        if ($bit == 1)
        {
            return $this->binDecode($binary, $mid, $max);
        }
        else
        {
            return $this->binDecode($binary, $min, $mid);
        }
    }

}

使用方式

$geo = new Geohash();
$latitude = '120.33.22.3';
$longitude = '310.23.132';
//获取gao算法加密字符串
$geohashVal = $geo->encode($latitude,$longitude);

//把$geohashVal插入数据表即可

 #查询附近的人
 $geo = new Geohash();
 $geohash = $geo->encode($latitude,$longitude);
 //切割长度是位置的距离线 
 $prefix = substr($geohash, 0, 6);
 $so = array_values($geo->neighbors($prefix));
 
 //$so是一个索引二维数组,相对8个位置角度,具体可打印测试

非常角度的方式使用咯

 

 

开源中国的GIT webhook钩子的php版本

php代码

<?php
/**
 * 写日记
 * @param str $msg
 */
function writeLog($msg,$file='')
{
    date_default_timezone_set("Asia/Shanghai");
    $dir = __DIR__.'/log/';
    if(!empty($file))
    {
        $file = $dir.$file;
    }else{
    	$file = $dir.'hook.log';
    }

    if (!file_exists ( $file ))
    {
    	 touch ( $file );
    }
    $info = "\r\n".date('Y-m-d H/i/s').': '.$msg;
    $fh = fopen ( $file, 'a+' );
    fwrite ( $fh, $info);
    fclose ( $fh );
}

if(isset($_POST['hook']))
{
    
	$passwd = '';//这里是您的KEY
	$hookJson = $_POST['hook'];
	writeLog($hookJson,'hook_json.log');
	if($json = json_decode($hookJson))
	{
		if($json->password === $passwd)
		{
			echo exec('/root/toinwork.sh');
			writeLog('toinwork执行成功','success.log');
		}	
	}else{
		writeLog('toinwork,hook密码不正确..执行失败','failure.log');
	}
}

shell执行脚本

#!/bin/bash
WEB_PATH='you is path'
WEB_USER='nginx'
WEB_USERGROUP='nginx'

echo "Start deployment"
cd $WEB_PATH
echo "pulling source code..."
git reset --hard origin/develop
git clean -f
git pull
git checkout develop
echo "changing permissions..."
chown -R $WEB_USER:$WEB_USERGROUP $WEB_PATH
echo "Finished."

请配置执行权限和用户组和用户

centos6.5 安装git 最新版本

#安装git需要的库
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
yum install gcc perl-ExtUtils-MakeMaker

#删除自带的git
yum remove git

#切换到目录
cd /usr/src

#可以去看看需要的版本号
https://www.kernel.org/pub/software/scm/git/

#这里选择下载git2.7.0版本
wget https://www.kernel.org/pub/software/scm/git/git-2.7.0.tar.gz

#解压缩
tar -zxvf git-2.7.0.tar.gz

#切换到git-2.7.0目录
cd git-2.7.0

#开始验证
./configure

#编译安装
make prefix=/usr/local/git all
make prefix=/usr/local/git install
echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc
source /etc/bashrc

#查看版本号
git --version

centos6.5 yum 安装php7,nginx1.8.1

#更新系统服务

yum -y update

#导入remi源

#64
rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

#32
rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

#资源库
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

#创建nginx.repo源文件

touch /etc/yum.repos.d/nginx.repo

#打开源文件内容

vim /etc/yum.repos.d/nginx.repo

#编辑器源文件内容

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

 

#更新源

yum --enablerepo=remi -y update 

#安装服务 php70,mysql,nginx,php-fpm
yum -y --enablerepo=remi,remi-php70 install nginx php-fpm php-common

#安装PHP模块
yum -y --enablerepo=remi,remi-php70 install php-opcache php-pecl-apcu php-cli php-pear php-pdo php-mysqlnd php-pgsql php-pecl-mongodb php-pecl-redis php-pecl-memcache php-pecl-memcached php-gd php-mbstring php-mcrypt php-xml

#安装Mysql
yum -y install mysql mysql-server

#安装mysql扩展
yum -y install mysql-connector-odbc mysql-devel libdbi-dbd-mysql

#创建fastcgi.conf
touch /etc/nginx/fastcgi.conf

#打开fastcgi.conf
vim /etc/nginx/fastcgi.conf

#编辑fastcgi.conf

if ($request_filename ~* (.*)\.php) {
set $php_url $1;
}
if (!-e $php_url.php) {
return 403;
}
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;

fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;

fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;

fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;

#打开nginx.conf (ps:我的nginx是最新文档版本1.8.1)
vim /etc/nginx/nginx.conf

#编辑以下内容

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 65535;

events
{
use epoll;
worker_connections 65535;
}

http
{
include /etc/nginx/mime.types;
default_type application/octet-stream;

server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 8m;

sendfile on;
tcp_nopush on;

keepalive_timeout 15;

tcp_nodelay on;

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
gzip_disable msie6;
#limit_zone crawler $binary_remote_addr 10m;
log_format '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#access_log /var/log/nginx/access.log main;
include /etc/nginx/conf.d/*.conf;
}

#设置nginx 自启服务
/sbin/chkconfig --add nginx
/sbin/chkconfig nginx on

#nginx 启动
/sbin/service nginx start

#设置php-fpm 自启服务
/sbin/chkconfig --add php-fpm
/sbin/chkconfig php-fpm on

#php-fpm 启动
/sbin/service php-fpm start

#添加mysql 自启服务
/sbin/chkconfig --add mysqld
/sbin/chkconfig mysqld on

#mysql 启动
/sbin/service mysqld start

#设置MYSQL密码
mysqladmin -u root password 'new passwd'
#打开mysql
mysql -u root -p
#删除test数据库
DROP DATABASE test;
#删除匿名帐户
DELETE FROM mysql.user WHERE user ='';
#重载权限
FLUSH PRIVILEGES;

#设置一个独立的nginx 虚拟主机配置
cd /etc/nginx/conf.d

#创建一条zmq.conf
touch zmq.conf

#打开zmq.conf
vim zmq.conf

#编辑以下内容,对应请修改需要的ROOT目录

server {
listen 80;
server_name Domain name
index index.html index.htm index.php;
root you in path
location ~ .*\.(php|php5|php7)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 1h;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
access_log you in url/you in name.log;
}

其余提示

php-fpm 需要配置相关的权限

nginx 执行的程序目录也需要配置权限

php写守护进程(Daemon)(转载)

PHP是否可以写守护进程?我觉得是可以的,业务不同,场景不同,产生的效果也不同,以下该文章很不错,特意转载过来

来源:http://blog.csdn.net/tengzhaorong/article/details/9764655

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。php也可以实现守护进程的功能。

1、基本概念
进程每个进程都有一个父进程,子进程退出,父进程能得到子进程退出的状态。
进程组每个进程都属于一个进程组,每个进程组都有一个进程组号,该号等于该进程组组长的PID

2、守护编程要点
1. 在后台运行。
为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。 if($pid=pcntl_fork()) exit(0);//是父进程,结束父进程,子进程继续
2. 脱离控制终端,登录会话和进程组
有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终 端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: posix_setsid();
说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。
3. 禁止进程重新打开控制终端
现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端: if($pid=pcntl_fork()) exit(0);//结束第一子进程,第二子进程继续(第二子进程不再是会话组长)
4. 关闭打开的文件描述符
进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们:
fclose(STDIN),fclose(STDOUT),fclose(STDERR)关闭标准输入输出与错误显示。
5. 改变当前工作目录
进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如chdir("/")
6. 重设文件创建掩模
进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0);
7. 处理SIGCHLD信号
处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影 响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。 signal(SIGCHLD,SIG_IGN);
这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。google so "Linux 信号说明列表"

3、实例

< ?php /** *@author tengzhaorong@gmail.com *@date 2013-07-25 * 后台脚本控制类 */ class DaemonCommand{ private $info_dir="/tmp"; private $pid_file=""; private $terminate=false; //是否中断 private $workers_count=0; private $gc_enabled=null; private $workers_max=8; //最多运行8个进程 public function __construct($is_sington=false,$user='nobody',$output="/dev/null"){ $this->is_sington=$is_sington; //是否单例运行,单例运行会在tmp目录下建立一个唯一的PID
$this->user=$user;//设置运行的用户 默认情况下nobody
$this->output=$output; //设置输出的地方
$this->checkPcntl();
}
//检查环境是否支持pcntl支持
public function checkPcntl(){
if ( ! function_exists('pcntl_signal_dispatch')) {
// PHP < 5.3 uses ticks to handle signals instead of pcntl_signal_dispatch // call sighandler only every 10 ticks declare(ticks = 10); } // Make sure PHP has support for pcntl if ( ! function_exists('pcntl_signal')) { $message = 'PHP does not appear to be compiled with the PCNTL extension. This is neccesary for daemonization'; $this->_log($message);
throw new Exception($message);
}
//信号处理
pcntl_signal(SIGTERM, array(__CLASS__, "signalHandler"),false);
pcntl_signal(SIGINT, array(__CLASS__, "signalHandler"),false);
pcntl_signal(SIGQUIT, array(__CLASS__, "signalHandler"),false);

// Enable PHP 5.3 garbage collection
if (function_exists('gc_enable'))
{
gc_enable();
$this->gc_enabled = gc_enabled();
}
}

// daemon化程序
public function daemonize(){

global $stdin, $stdout, $stderr;
global $argv;

set_time_limit(0);

// 只允许在cli下面运行
if (php_sapi_name() != "cli"){
die("only run in command line mode\n");
}

// 只能单例运行
if ($this->is_sington==true){

$this->pid_file = $this->info_dir . "/" .__CLASS__ . "_" . substr(basename($argv[0]), 0, -4) . ".pid";
$this->checkPidfile();
}

umask(0); //把文件掩码清0

if (pcntl_fork() != 0){ //是父进程,父进程退出
exit();
}

posix_setsid();//设置新会话组长,脱离终端

if (pcntl_fork() != 0){ //是第一子进程,结束第一子进程
exit();
}

chdir("/"); //改变工作目录

$this->setUser($this->user) or die("cannot change owner");

//关闭打开的文件描述符
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);

$stdin = fopen($this->output, 'r');
$stdout = fopen($this->output, 'a');
$stderr = fopen($this->output, 'a');

if ($this->is_sington==true){
$this->createPidfile();
}

}

//--检测pid是否已经存在
public function checkPidfile(){

if (!file_exists($this->pid_file)){
return true;
}
$pid = file_get_contents($this->pid_file);
$pid = intval($pid);
if ($pid > 0 && posix_kill($pid, 0)){
$this->_log("the daemon process is already started");
}
else {
$this->_log("the daemon proces end abnormally, please check pidfile " . $this->pid_file);
}
exit(1);

}
//----创建pid
public function createPidfile(){

if (!is_dir($this->info_dir)){
mkdir($this->info_dir);
}
$fp = fopen($this->pid_file, 'w') or die("cannot create pid file");
fwrite($fp, posix_getpid());
fclose($fp);
$this->_log("create pid file " . $this->pid_file);
}

//设置运行的用户
public function setUser($name){

$result = false;
if (empty($name)){
return true;
}
$user = posix_getpwnam($name);
if ($user) {
$uid = $user['uid'];
$gid = $user['gid'];
$result = posix_setuid($uid);
posix_setgid($gid);
}
return $result;

}
//信号处理函数
public function signalHandler($signo){

switch($signo){

//用户自定义信号
case SIGUSR1: //busy
if ($this->workers_count < $this->workers_max){
$pid = pcntl_fork();
if ($pid > 0){
$this->workers_count ++;
}
}
break;
//子进程结束信号
case SIGCHLD:
while(($pid=pcntl_waitpid(-1, $status, WNOHANG)) > 0){
$this->workers_count --;
}
break;
//中断进程
case SIGTERM:
case SIGHUP:
case SIGQUIT:

$this->terminate = true;
break;
default:
return false;
}

}
/**
*开始开启进程
*$count 准备开启的进程数
*/
public function start($count=1){

$this->_log("daemon process is running now");
pcntl_signal(SIGCHLD, array(__CLASS__, "signalHandler"),false); // if worker die, minus children num
while (true) {
if (function_exists('pcntl_signal_dispatch')){

pcntl_signal_dispatch();
}

if ($this->terminate){
break;
}
$pid=-1;
if($this->workers_count< $count){ $pid=pcntl_fork(); } if($pid>0){

$this->workers_count++;

}elseif($pid==0){

// 这个符号表示恢复系统对信号的默认处理
pcntl_signal(SIGTERM, SIG_DFL);
pcntl_signal(SIGCHLD, SIG_DFL);
if(!empty($this->jobs)){
while($this->jobs['runtime']){
if(empty($this->jobs['argv'])){
call_user_func($this->jobs['function'],$this->jobs['argv']);
}else{
call_user_func($this->jobs['function']);
}
$this->jobs['runtime']--;
sleep(2);
}
exit();

}
return;

}else{

sleep(2);
}

}

$this->mainQuit();
exit(0);

}

//整个进程退出
public function mainQuit(){

if (file_exists($this->pid_file)){
unlink($this->pid_file);
$this->_log("delete pid file " . $this->pid_file);
}
$this->_log("daemon process exit now");
posix_kill(0, SIGKILL);
exit(0);
}

// 添加工作实例,目前只支持单个job工作
public function setJobs($jobs=array()){

if(!isset($jobs['argv'])||empty($jobs['argv'])){

$jobs['argv']="";

}
if(!isset($jobs['runtime'])||empty($jobs['runtime'])){

$jobs['runtime']=1;

}

if(!isset($jobs['function'])||empty($jobs['function'])){

$this->log("你必须添加运行的函数!");
}

$this->jobs=$jobs;

}
//日志处理
private function _log($message){
printf("%s\t%d\t%d\t%s\n", date("c"), posix_getpid(), posix_getppid(), $message);
}

}

demo code:


//调用方法1
$daemon=new DaemonCommand(true);
$daemon->daemonize();
$daemon->start(2);//开启2个子进程工作
work();

//调用方法2
$daemon=new DaemonCommand(true);
$daemon->daemonize();
//function 要运行的函数,argv运行函数的参数,runtime运行的次数
$daemon->addJobs(array('function'=>'work','argv'=>'','runtime'=>1000));
$daemon->start(2);//开启2个子进程工作

//具体功能的实现
function work(){
echo "测试1";
}

mac 配置golng开发环境

第一步:官网下载pkg包安装
默认路径:/usr/local/go

配置全局变量:

vim ~/.bash_profile

输入以下内容:

export GOROOT=/usr/local/go

export PATH=/usr/local/go/bin:$PATH

export GOPATH=你自己平时将go代码放置的地方

执行生效

source ~/. bash_profile

查看版本

go version

Mac 下 php多版本切换

php-version是一个帮助管理从brew安装的php版本切换的工具。

 

安装

brew install php-version

执行全局命令

source $(brew --prefix php-version)/php-version.sh && php-version 5

执行

php-version

可以看见安装的PHP

5.6.4

*5.5.30

 

然后使用以下命令切换即可

php-version 5.6.4

 

手动安装Homebrew

到Github官网上搜索Homebrew,找到对应的Homebrew后,查看它的安装文档,链接如下:

https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Installation.md

安装要求OS X 10.6以上系统,并且安装有XCode命令行工具。

安装路径不能有空格。官方建议安装在/usr/local路径下。

打开Mac的终端。进入该路径,然后执行安装文档中的命令即可。

cd /usr/local
mkdir homebrew
curl -L https://github.com/Homebrew/homebrew/tarball/master | tar xz --strip 1 -C homebrew

上面的安装只是将Homebrew解压到本地,还需要配置环境变量才能使用brew命令,否则终端会提示Command Not Found。

第一次配置Mac的环境变量,到网上转了一圈才找到正确方法。

打开终端,新建.bash_profile文件在~/目录下(如果电脑里已经有了这个文件,跳过这一步)

touch ~/.bash_profile

打开.bash_profile

open ~/.bash_profile

在弹出的编辑窗口中配置PATH

export PATH=/usr/local/homebrew/bin:$PATH

然后再回到终端输入,使文件生效。

source ~/.bash_profile

至此,环境变量配置完成。

 

终端

brew -v

 

Mac下通过 brew 安装不同版本的php和扩展

第一步,先安装 brew    Brew 是 Mac 下面的包管理工具,通过 Github 托管适合 Mac 的编译配置以及 Patch,可以方便的安装开发工具。 Mac 自带ruby 所以安装起来很方便,同时它也会自动把git也给你装上。官方网站: http://brew.sh    在mac下终端里直接输入命令行:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安装完成之后,建议执行一下自检:brew doctor 如果看到Your system is ready to brew. 那么你的brew已经可以开始使用了。    常用命令: (所有软件以PHP5.5为例子)

brew update                        #更新brew可安装包,建议每次执行一下
brew search php55                  #搜索php5.5
brew tap josegonzalez/php          #安装扩展<gihhub_user/repo>
brew tap                           #查看安装的扩展列表
brew install php55                 #安装php5.5
brew remove  php55                 #卸载php5.5
brew upgrade php55                 #升级php5.5
brew options php55                 #查看php5.5安装选项
brew info    php55                 #查看php5.5相关信息
brew home    php55                 #访问php5.5官方网站
brew services list                 #查看系统通过 brew 安装的服务
brew services cleanup              #清除已卸载无用的启动配置文件
brew services restart php55        #重启php-fpm

第二步,安装PHP

先添加brew的PHP扩展库:

brew update
brew tap homebrew/dupes
brew tap homebrew/php
brew tap josegonzalez/homebrew-php

可以使用 brew options php53 命令来查看安装php5.3的选项,这里我用下面的选项安装:

brew install php53 --with-apache --with-gmp --with-imap --with-tidy --with-debug

请注意:如果你希望以mac下的apache作为web server,编译时要加 --with-apache;如果你的web server 是 nginx这类,就需要加上 --with-fpm。

Options
--disable-opcache
Build without Opcache extension
--disable-zend-multibyte
Disable auto-detection of Unicode encoded scripts
--homebrew-apxs
Build against apxs in Homebrew prefix
--with-apache
Enable building of shared Apache 2.0 Handler module, overriding any options which disable apache
--with-cgi
Enable building of the CGI executable (implies --without-apache)
--with-debug
Compile with debugging symbols
--with-fpm
Enable building of the fpm SAPI executable (implies --without-apache)
--with-gmp
Build with gmp support
--with-homebrew-curl
Include Curl support via Homebrew
--with-homebrew-libxslt
Include LibXSLT support via Homebrew
--with-homebrew-openssl
Include OpenSSL support via Homebrew
--with-imap
Include IMAP extension
--with-libmysql
Include (old-style) libmysql support instead of mysqlnd
--with-mssql
Include MSSQL-DB support
--with-pdo-oci
Include Oracle databases (requries ORACLE_HOME be set)
--with-phpdbg
Enable building of the phpdbg SAPI executable (PHP 5.4 and above)
--with-postgresql
Build with postgresql support
--with-thread-safety
Build with thread safety
--with-tidy
Include Tidy support
--without-bz2
Build without bz2 support
--without-mysql
Remove MySQL/MariaDB support
--without-pcntl
Build without Process Control support
--without-pear
Build without PEAR
--without-snmp
Build without SNmp support
--HEAD
Install HEAD version

PHP编译过程中如果遇到 configure: error: Cannot find OpenSSL's <evp.h> 错误,执行 xcode-select --install 重新安装一下 Xcode Command Line Tools 即可解决该错误(来源:https://github.com/Homebrew/homebrew-php/issues/1181)。     安装完php后,会有一段提示,请仔细阅读:

Caveats
To enable PHP in Apache add the following to httpd.conf and restart Apache:
LoadModule php5_module    /usr/local/opt/php53/libexec/apache2/libphp5.soThe php.ini file can be found in:
/usr/local/etc/php/5.3/php.ini✩✩✩✩ PEAR ✩✩✩✩If PEAR complains about permissions, 'fix' the default PEAR permissions and config:
chmod -R ug+w /usr/local/Cellar/php53/5.3.29/lib/php
pear config-set php_ini /usr/local/etc/php/5.3/php.ini✩✩✩✩ Extensions ✩✩✩✩If you are having issues with custom extension compiling, ensure that
you are using the brew version, by placing /usr/local/bin before /usr/sbin in your PATH:      PATH="/usr/local/bin:$PATH"PHP53 Extensions will always be compiled against this PHP. Please install them
using --without-homebrew-php to enable compiling against system PHP.✩✩✩✩ PHP CLI ✩✩✩✩If you wish to swap the PHP you use on the command line, you should add the following to ~/.bashrc,
~/.zshrc, ~/.profile or your shell's equivalent configuration file:      export PATH="$(brew --prefix homebrew/php/php53)/bin:$PATH"To have launchd start php53 at login:
 ln -sfv /usr/local/opt/php53/*.plist ~/Library/LaunchAgents
Then to load php53 now:
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.php53.plist
==> Summary
/usr/local/Cellar/php53/5.3.29: 480 files, 31M, built in 12.9 minutes

等待PHP编译完成,开始安装PHP常用扩展,扩展安装过程中 brew会自动安装依赖包,使用 brew search php53- 命令,可以查看还有哪些扩展可以安装,然后执行 brew install php53-XXX 就可以了。     由于Mac自带了php和php-fpm,因此需要添加系统环境变量PATH来替代自带PHP版本:

echo 'export PATH="$(brew --prefix homebrew/php/php53)/bin:$PATH"' >> ~/.bash_profile  #for php
echo 'export PATH="$(brew --prefix homebrew/php/php53)/sbin:$PATH"' >> ~/.bash_profile  #for php-fpm
echo 'export PATH="/usr/local/bin:/usr/local/sbin:$PATH"' >> ~/.bash_profile #for other brew install soft
source ~/.bash_profile  #更新配置

如何卸载安装的 php5.3呢?

# 卸载
brew uninstall php53
# 清除缓存以及老旧版本文件
brew cleanup -s

测试一下效果:

$ php -v
PHP 5.3.29 (cli) (built: Jan 24 2015 12:40:58) (DEBUG)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2014 Zend Technologies# mac系统自带的php
$ /usr/bin/php -v
PHP 5.4.30 (cli) (built: Jul 29 2014 23:43:29)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
with Zend Guard Loader v3.3, Copyright (c) 1998-2013, by Zend Technologies

由于我们没有安装php的fpm模式,所以 php-fpm -v 命令显示的是mac自带的:

$ php-fpm -v
PHP 5.4.30 (fpm-fcgi) (built: Jul 29 2014 23:44:15)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
with Zend Guard Loader v3.3, Copyright (c) 1998-2013, by Zend Technologies

这个时候,我们使用 phpinfo 函数显示出来的php版本还是max自带的PHP5.4,需要我们修改 apache的配置文件 httpd.conf,加载的php5模块路径指向刚刚安装的 php5.3目录里的 libphp5.so:

LoadModule php5_module    /usr/local/opt/php53/libexec/apache2/libphp5.so

重启apache,phpinfo() 脚本里显示的 php 版本就变成了 PHP Version 5.3.29。