PHP扩展详解

前言

如何编写PHP扩展的文章已经很多很多,最近一个项目需要使用相对比较深入,权当整理一份笔记吧。

简介

PHP语言,代码编写简单、函数实用、扩展丰富、深受网站开发者青睐,非常适合业务开发。但某些特定的场合,我们需要特殊的函数,定制的服务扩展,那么就需要自己动手编写PHP扩展满足业务需求。

场景

1、特殊的函数,提高函数性能。(PHP函数库未提供函数,或使用系统函数不满足业务需求,C定制性能会更佳)
2、定制服务扩展 (如新服务的驱动、只提供了C的API,扩展后方便在PHP中使用等)

扩展一个简单的函数
=====================================================================

0、PHP扩展中有一个函数 int crc32 ( string $str ) (32位循环冗余校验码多项式。这通常用于检查传输的数据是否完整。)然与C数据交换的过程,16位循环冗余校验码多项式即可;固需扩展函数 int CalcCrc16( string $str )

1、找到你正在使用的PHP版本源码的根目录,我们定义好头文件

vi mfun.def

string CalcCrc16(string str)


2、生成扩展的代码框架,根据定义生成函数

cd ext/
./ext_skel –extname=mfun –proto=../mfun.def

config.m4 配置文件
php_mfun.h 函数头文件
mfun.c 扩展C主文件

3、修改配置文件,此函数比较简单,不涉及三方C库,开启–enable-mfun 方式即可

vi mfun/config.m4

dnl $Id$
dnl config.m4 for extension mfun

dnl Comments in this file start with the string 'dnl'.
dnl Remove where necessary. This file will not work
dnl without editing.

dnl If your extension references something external, use with:

dnl PHP_ARG_WITH(mfun, for mfun support,
dnl Make sure that the comment is aligned:
dnl [  --with-mfun             Include mfun support])

dnl Otherwise use enable:

PHP_ARG_ENABLE(mfun, whether to enable mfun support,
[  --enable-mfun           Enable mfun support])

if test "$PHP_MFUN" != "no"; then
  dnl Write more examples of tests here...

  dnl # --with-mfun -> check with-path
  dnl SEARCH_PATH="/usr/local /usr"     # you might want to change this
  dnl SEARCH_FOR="/include/mfun.h"  # you most likely want to change this
  dnl if test -r $PHP_MFUN/$SEARCH_FOR; then # path given as parameter
  dnl   MFUN_DIR=$PHP_MFUN
  dnl else # search default path list
  dnl   AC_MSG_CHECKING([for mfun files in default path])
  dnl   for i in $SEARCH_PATH ; do
  dnl     if test -r $i/$SEARCH_FOR; then
  dnl       MFUN_DIR=$i
  dnl       AC_MSG_RESULT(found in $i)
  dnl     fi
  dnl   done
  dnl fi
  dnl
  dnl if test -z "$MFUN_DIR"; then
  dnl   AC_MSG_RESULT([not found])
  dnl   AC_MSG_ERROR([Please reinstall the mfun distribution])
  dnl fi

  dnl # --with-mfun -> add include path
  dnl PHP_ADD_INCLUDE($MFUN_DIR/include)

  dnl # --with-mfun -> check for lib and symbol presence
  dnl LIBNAME=mfun # you may want to change this
  dnl LIBSYMBOL=mfun # you most likely want to change this 

  dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
  dnl [
  dnl   PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $MFUN_DIR/lib, MFUN_SHARED_LIBADD)
  dnl   AC_DEFINE(HAVE_MFUNLIB,1,[ ])
  dnl ],[
  dnl   AC_MSG_ERROR([wrong mfun lib version or lib not found])
  dnl ],[
  dnl   -L$MFUN_DIR/lib -lm
  dnl ])
  dnl
  dnl PHP_SUBST(MFUN_SHARED_LIBADD)

  PHP_NEW_EXTENSION(mfun, mfun.c, $ext_shared)
fi

4、修改函数头文件,PHP_FUNCTION 注册函数

vi mfun/php_mfun.h

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifndef PHP_MFUN_H
#define PHP_MFUN_H

extern zend_module_entry mfun_module_entry;
#define phpext_mfun_ptr &mfun_module_entry

#define PHP_MFUN_VERSION "0.1.0" /* Replace with version number for your extension */

#ifdef PHP_WIN32
#	define PHP_MFUN_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#	define PHP_MFUN_API __attribute__ ((visibility("default")))
#else
#	define PHP_MFUN_API
#endif

#ifdef ZTS
#include "TSRM.h"
#endif

PHP_MINIT_FUNCTION(mfun);
PHP_MSHUTDOWN_FUNCTION(mfun);
PHP_RINIT_FUNCTION(mfun);
PHP_RSHUTDOWN_FUNCTION(mfun);
PHP_MINFO_FUNCTION(mfun);

PHP_FUNCTION(confirm_mfun_compiled);	/* For testing, remove later. */
PHP_FUNCTION(CalcCrc16);

/* 
  	Declare any global variables you may need between the BEGIN
	and END macros here:     

ZEND_BEGIN_MODULE_GLOBALS(mfun)
	long  global_value;
	char *global_string;
ZEND_END_MODULE_GLOBALS(mfun)
*/

/* In every utility function you add that needs to use variables 
   in php_mfun_globals, call TSRMLS_FETCH(); after declaring other 
   variables used by that function, or better yet, pass in TSRMLS_CC
   after the last function argument and declare your utility function
   with TSRMLS_DC after the last declared argument.  Always refer to
   the globals in your function as MFUN_G(variable).  You are 
   encouraged to rename these macros something shorter, see
   examples in any other php module directory.
*/

#ifdef ZTS
#define MFUN_G(v) TSRMG(mfun_globals_id, zend_mfun_globals *, v)
#else
#define MFUN_G(v) (mfun_globals.v)
#endif

#endif	/* PHP_MFUN_H */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */

5、编写主文件 PHP_FUNCTION(CalcCrc16)

完成对函数PHP_FUNCTION(CalcCrc16)的扩展;主要分为三部分

5.1、扩展的标准输入,此处输入为字符串,标准输入函数生成长度以及校验 (关于扩展的输入输出详解,参考附录)

char *str = NULL;
int argc = ZEND_NUM_ARGS();
int str_len;

if (zend_parse_parameters(argc TSRMLS_CC, "s", &str, &str_len) == FAILURE) 
    return;

5.2、编写内容

CRC16标准C算法

5.3、扩展的标准输出,此处输出为字符串(关于扩展的输入输出详解,参考附录)

RETURN_LONG(cRc_16);

vi mfun/mfun.c

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_mfun.h"

/* If you declare any globals in php_mfun.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(mfun)
*/

/* True global resources - no need for thread safety here */
static int le_mfun;

/* {{{ mfun_functions[]
 *
 * Every user visible function must have an entry in mfun_functions[].
 */
const zend_function_entry mfun_functions[] = {
	PHP_FE(confirm_mfun_compiled,	NULL)		/* For testing, remove later. */
	PHP_FE(CalcCrc16,	NULL)
	PHP_FE_END	/* Must be the last line in mfun_functions[] */
};
/* }}} */

/* {{{ mfun_module_entry
 */
zend_module_entry mfun_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"mfun",
	mfun_functions,
	PHP_MINIT(mfun),
	PHP_MSHUTDOWN(mfun),
	PHP_RINIT(mfun),		/* Replace with NULL if there's nothing to do at request start */
	PHP_RSHUTDOWN(mfun),	/* Replace with NULL if there's nothing to do at request end */
	PHP_MINFO(mfun),
#if ZEND_MODULE_API_NO >= 20010901
	PHP_MFUN_VERSION,
#endif
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_MFUN
ZEND_GET_MODULE(mfun)
#endif

/* {{{ PHP_INI
 */
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY("mfun.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_mfun_globals, mfun_globals)
    STD_PHP_INI_ENTRY("mfun.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_mfun_globals, mfun_globals)
PHP_INI_END()
*/
/* }}} */

/* {{{ php_mfun_init_globals
 */
/* Uncomment this function if you have INI entries
static void php_mfun_init_globals(zend_mfun_globals *mfun_globals)
{
	mfun_globals->global_value = 0;
	mfun_globals->global_string = NULL;
}
*/
/* }}} */

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(mfun)
{
	/* If you have INI entries, uncomment these lines 
	REGISTER_INI_ENTRIES();
	*/
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(mfun)
{
	/* uncomment this line if you have INI entries
	UNREGISTER_INI_ENTRIES();
	*/
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(mfun)
{
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(mfun)
{
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(mfun)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "mfun support", "enabled");
	php_info_print_table_header(2, "CalcCrc16", "enabled");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini
	DISPLAY_INI_ENTRIES();
	*/
}
/* }}} */


/* Remove the following function when you have successfully modified config.m4
   so that your module can be compiled into PHP, it exists only for testing
   purposes. */

/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_mfun_compiled(string arg)
   Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_mfun_compiled)
{
	char *arg = NULL;
	int arg_len, len;
	char *strg;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
		return;
	}

	len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "mfun", arg);
	RETURN_STRINGL(strg, len, 0);
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and 
   unfold functions in source code. See the corresponding marks just before 
   function definition, where the functions purpose is also documented. Please 
   follow this convention for the convenience of others editing your code.
*/

/* {{{ proto string CalcCrc16(string str)
    */
PHP_FUNCTION(CalcCrc16)
{
	char *str = NULL;
	int argc = ZEND_NUM_ARGS();
	int str_len;

	if (zend_parse_parameters(argc TSRMLS_CC, "s", &str, &str_len) == FAILURE) 
		return;

	//printf("str=%s\n", str);
	//printf("str_len=%d\n", str_len);

	unsigned short cRc_16 = 0x0000;
	const unsigned short cnCRC_16 = 0x8005;
	unsigned long cRctable_16[256];
	unsigned short i,j,k;

	for (i=0,k=0;i<256;i++,k++)
	{
		cRc_16 = i<<8;
		for (j=8;j>0;j--)
		{
			if (cRc_16&0x8000)
			cRc_16 = (cRc_16<<=1)^cnCRC_16;
			else
			cRc_16<<=1;
		}
		cRctable_16[k] = cRc_16;
	}

	while (str_len>0)
	{
		cRc_16 = (cRc_16 << 8) ^ cRctable_16[((cRc_16>>8) ^ *str) & 0xff];
		str_len--;
		str++;
	}

	RETURN_LONG(cRc_16);

}
/* }}} */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */

扩展一个复杂的操作库
=====================================================================

0、大多我们使用的服务(Mysql、Memcached等),PHP官方已经提供了相关扩展;但是如果是自己C语言写的一个服务或者只有C语言版的服务,我们为了方便在PHP中使用,最好的办法就是编写成PHP扩展直接调用。随便说两句,其他语言给PHP提供相关服务的方式有很多,如通过Socket的方式、Thrift跨语言框架等。

0.1、PHP扩展方式比较适用于单线程服务;如果是多线程的涉及线程安全问题,具体可以参考pthreads(http://www.php.net/manual/en/book.pthreads.php) 编译PHP是需要 –enable-maintainer-zts 增强线程安全
0.2、Socket方式实用场景较多,所有语言都支持,但实际实用过程中相对麻烦,各个语言实现不一致,规范化与协议需制定
0.3、Thrift框架,相当于封装过的Socket,跨语言和开发成本都会降低 (待单起博文详解)

1、根据C服务的头文件,定义需要扩展的函数,扩展为操作C库提供的对USBkey的操作

vi keys.def

string CGet_cinema_code()
string CSign_dataEx(string str)
string CVerify_dataEx(string str)
string CGet_public_key()
int CCreate_client_socket(callable callback, string ip, int port)
int getSocketStatus()
int CSend_message(string str)
int CGet_post_infoEx(callable callback, string str, string api, string ip, int port)
int CClose_socket()
int CMd5_dataEx(string str)

2、生成扩展框架

cd ext/
./ext_skel –extname=keys –proto=../keys.def

config.m4 配置文件
php_keys.h 函数头文件
keys.c 扩展C主文件

3、修改配置文件,配置开启 –with-keys,设置C动态库查找目录,设置头文件位置

dnl $Id$
dnl config.m4 for extension keys

dnl Comments in this file start with the string 'dnl'.
dnl Remove where necessary. This file will not work
dnl without editing.

dnl If your extension references something external, use with:

PHP_ARG_WITH(keys, for keys support,
[  --with-keys             Include keys support])

dnl Otherwise use enable:

dnl PHP_ARG_ENABLE(keys, whether to enable keys support,
dnl Make sure that the comment is aligned:
dnl [  --enable-keys           Enable keys support])

if test "$PHP_KEYS" != "no"; then
   Write more examples of tests here...

   # --with-keys -> check with-path
   SEARCH_PATH="/usr/local /usr"     # you might want to change this
   SEARCH_FOR="/include/Keys.h"  # you most likely want to change this
   if test -r $PHP_KEYS/$SEARCH_FOR; then # path given as parameter
     KEYS_DIR=$PHP_KEYS
   else # search default path list
     AC_MSG_CHECKING([for keys files in default path])
     for i in $SEARCH_PATH ; do
       if test -r $i/$SEARCH_FOR; then
         KEYS_DIR=$i
         AC_MSG_RESULT(found in $i)
       fi
     done
   fi

   if test -z "$KEYS_DIR"; then
     AC_MSG_RESULT([not found])
     AC_MSG_ERROR([Please reinstall the keys distribution])
   fi

   # --with-keys -> add include path
   PHP_ADD_INCLUDE($KEYS_DIR/include)

   # --with-keys -> check for lib and symbol presence
   LIBNAME=keys # you may want to change this
   LIBSYMBOL=CMd5_data # you most likely want to change this 

   PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
   [
     PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $KEYS_DIR/lib, KEYS_SHARED_LIBADD)
     AC_DEFINE(HAVE_KEYSLIB,1,[ ])
   ],[
     AC_MSG_ERROR([wrong keys lib version or lib not found])
   ],[
     -L$KEYS_DIR/lib -lm
   ])

   PHP_SUBST(KEYS_SHARED_LIBADD)

  PHP_NEW_EXTENSION(keys, keys.c, $ext_shared)
fi

4、修改函数头文件,PHP_FUNCTION 注册函数

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifndef PHP_KEYS_H
#define PHP_KEYS_H

extern zend_module_entry keys_module_entry;
#define phpext_keys_ptr &keys_module_entry

#define PHP_KEYS_VERSION "0.1.0" /* Replace with version number for your extension */

#ifdef PHP_WIN32
#	define PHP_KEYS_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#	define PHP_KEYS_API __attribute__ ((visibility("default")))
#else
#	define PHP_KEYS_API
#endif

#ifdef ZTS
#include "TSRM.h"
#endif

PHP_MINIT_FUNCTION(keys);
PHP_MSHUTDOWN_FUNCTION(keys);
PHP_RINIT_FUNCTION(keys);
PHP_RSHUTDOWN_FUNCTION(keys);
PHP_MINFO_FUNCTION(keys);

PHP_FUNCTION(confirm_keys_compiled);	/* For testing, remove later. */
PHP_FUNCTION(CGet_cinema_code);
PHP_FUNCTION(CSign_dataEx);
PHP_FUNCTION(CVerify_dataEx);
PHP_FUNCTION(CGet_public_key);
PHP_FUNCTION(CCreate_client_socket);
PHP_FUNCTION(getSocketStatus);
PHP_FUNCTION(CSend_message);
PHP_FUNCTION(CGet_post_infoEx);
PHP_FUNCTION(CClose_socket);
PHP_FUNCTION(CMd5_dataEx);

/* 
  	Declare any global variables you may need between the BEGIN
	and END macros here:     

ZEND_BEGIN_MODULE_GLOBALS(keys)
	long  global_value;
	char *global_string;
ZEND_END_MODULE_GLOBALS(keys)
*/

/* In every utility function you add that needs to use variables 
   in php_keys_globals, call TSRMLS_FETCH(); after declaring other 
   variables used by that function, or better yet, pass in TSRMLS_CC
   after the last function argument and declare your utility function
   with TSRMLS_DC after the last declared argument.  Always refer to
   the globals in your function as KEYS_G(variable).  You are 
   encouraged to rename these macros something shorter, see
   examples in any other php module directory.
*/

#ifdef ZTS
#define KEYS_G(v) TSRMG(keys_globals_id, zend_keys_globals *, v)
#else
#define KEYS_G(v) (keys_globals.v)
#endif

#endif	/* PHP_KEYS_H */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim

5、编写主文件 完成对扩展开发

其中,
PHP_MINIT_FUNCTION(keys) 为扩展运行前初始化
int mycreatebak(char *data, int len)作为回调函数,供其他函数回调;函数内部还包含了PHP扩展对PHP回调的标准输出。

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_keys.h"
#include "/root/linuxapi/include/PKCS11/cryptoki_ext.h"

/* If you declare any globals in php_keys.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(keys)
*/

/* True global resources - no need for thread safety here */
static int le_keys;

/* {{{ keys_functions[]
 *
 * Every user visible function must have an entry in keys_functions[].
 */
const zend_function_entry keys_functions[] = {
	PHP_FE(confirm_keys_compiled,	NULL)		/* For testing, remove later. */
	PHP_FE(CGet_cinema_code,	NULL)
	PHP_FE(CSign_dataEx,	NULL)
	PHP_FE(CVerify_dataEx,	NULL)
	PHP_FE(CGet_public_key,	NULL)
	PHP_FE(CCreate_client_socket,	NULL)
	PHP_FE(getSocketStatus,	NULL)
	PHP_FE(CSend_message,	NULL)
	PHP_FE(CGet_post_infoEx,	NULL)
	PHP_FE(CClose_socket,	NULL)
	PHP_FE(CMd5_dataEx,	NULL)
	PHP_FE_END	/* Must be the last line in keys_functions[] */
};
/* }}} */

/* {{{ keys_module_entry
 */
zend_module_entry keys_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"keys",
	keys_functions,
	PHP_MINIT(keys),
	PHP_MSHUTDOWN(keys),
	PHP_RINIT(keys),		/* Replace with NULL if there's nothing to do at request start */
	PHP_RSHUTDOWN(keys),	/* Replace with NULL if there's nothing to do at request end */
	PHP_MINFO(keys),
#if ZEND_MODULE_API_NO >= 20010901
	PHP_KEYS_VERSION,
#endif
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_KEYS
ZEND_GET_MODULE(keys)
#endif

/* {{{ PHP_INI
 */
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY("keys.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_keys_globals, keys_globals)
    STD_PHP_INI_ENTRY("keys.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_keys_globals, keys_globals)
PHP_INI_END()
*/
/* }}} */

/* {{{ php_keys_init_globals
 */
/* Uncomment this function if you have INI entries
static void php_keys_init_globals(zend_keys_globals *keys_globals)
{
	keys_globals->global_value = 0;
	keys_globals->global_string = NULL;
}
*/
/* }}} */

int mycreatebak(char *data, int len)
{
	printf("recv len=%d\n", len);
	int i;
	for (i = 0; i < len; i++)
	{
		if (len % 16 == 0) printf("\n");
		printf("%02x ", data[i]);
	}
	printf("\n");

	zval * function_name;
	zval * retval_ptr;
	zval * argv;

	MAKE_STD_ZVAL(function_name);
	MAKE_STD_ZVAL(retval_ptr);
	MAKE_STD_ZVAL(argv);

	ZVAL_STRINGL(function_name,"createbak",sizeof("createbak")-1,1);
	ZVAL_STRINGL(argv, data, len, 1);

	call_user_function(EG(function_table),NULL,function_name,retval_ptr,1,&argv TSRMLS_CC);

	zval_ptr_dtor(&function_name);
	zval_ptr_dtor(&retval_ptr);
	zval_ptr_dtor(&argv);
}

int mypostbak(char *data, int len)
{
	printf("recv len=%d\n", len);
	int i;
	for (i = 0; i < len; i++)
	{
		if (len % 16 == 0) printf("\n");
		printf("%02x ", data[i]);
	}
	printf("\n");

	zval * function_name;
	zval * retval_ptr;
	zval * argv;

	MAKE_STD_ZVAL(function_name);
	MAKE_STD_ZVAL(retval_ptr);
	MAKE_STD_ZVAL(argv);

	ZVAL_STRINGL(function_name,"postbak",sizeof("postbak")-1,1);
	ZVAL_STRINGL(argv, data, len, 1);

	call_user_function(EG(function_table),NULL,function_name,retval_ptr,1,&argv TSRMLS_CC);

	zval_ptr_dtor(&function_name);
	zval_ptr_dtor(&retval_ptr);
	zval_ptr_dtor(&argv);
}

int readmsg1(char *data, int len)
{
	printf("recv len=%d\n", len);
	printf("输入的内容为: %s\n", data);
	printf("\n");
	return 0;
}

void PrintHex(void *buf, int len)
{
	int i;
	for (i = 0; i < len; i++)
	{
		if (i % 16 == 0) printf("\n");
		printf("%02x ", *((unsigned char *)buf+i));
	}
	printf("\n------------------------\n");
}

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(keys)
{
	/* If you have INI entries, uncomment these lines 
	REGISTER_INI_ENTRIES();
	*/

	// 初始化环境
	int ret = CInit_Env();
	printf("CInit_Env = %d\n", ret);
	SetFilePath("/root/linuxapi/demo/");

	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(keys)
{
	/* uncomment this line if you have INI entries
	UNREGISTER_INI_ENTRIES();
	*/
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(keys)
{
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(keys)
{
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(keys)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "keys support", "enabled");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini
	DISPLAY_INI_ENTRIES();
	*/
}
/* }}} */

/* Remove the following function when you have successfully modified config.m4
   so that your module can be compiled into PHP, it exists only for testing
   purposes. */

/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_keys_compiled(string arg)
   Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_keys_compiled)
{
	char *arg = NULL;
	int arg_len, len;
	char *strg;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
		return;
	}

	len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "keys", arg);
	RETURN_STRINGL(strg, len, 0);
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and 
   unfold functions in source code. See the corresponding marks just before 
   function definition, where the functions purpose is also documented. Please 
   follow this convention for the convenience of others editing your code.
*/

/* {{{ proto string CGet_cinema_code()
    */
PHP_FUNCTION(CGet_cinema_code)
{
	int ret;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	//pub key
	unsigned char pub1[128];
	unsigned char pub2[3];

	ret = CGet_public_key(pub1, pub2);
	printf("CGet_public_key=%d\n", ret);

	char *cinemacode;
	cinemacode = CGet_cinema_code();
    printf("CGet_cinema_code=%s\n", cinemacode);

	RETURN_STRING(cinemacode,0);

}
/* }}} */

/* {{{ proto string CSign_dataEx(string str)
    */
PHP_FUNCTION(CSign_dataEx)
{
	char *str = NULL;
	int argc = ZEND_NUM_ARGS();
	int str_len;
	long len;
	int ret;

	if (zend_parse_parameters(argc TSRMLS_CC, "s", &str, &str_len) == FAILURE) 
		return;

	//pub key
	unsigned char pub1[128];
	unsigned char pub2[3];

	ret = CGet_public_key(pub1, pub2);
	printf("CGet_public_key=%d\n", ret);

	char outbuf[1024];
	CK_ULONG signoutlen = sizeof(outbuf);
	ret = CSign_dataEx(str, str_len, outbuf, signoutlen);
	printf("CSign_dataEx=%d\n", ret);
	PrintHex(outbuf, signoutlen);

	RETURN_STRINGL(outbuf,signoutlen,0);
}
/* }}} */

/* {{{ proto string CVerify_dataEx(string str)
    */
PHP_FUNCTION(CVerify_dataEx)
{
	char *str = NULL;
	char *outbuf = NULL;
	int argc = ZEND_NUM_ARGS();
	int str_len;
	int signoutlen;
	int ret;

	if (zend_parse_parameters(argc TSRMLS_CC, "ss", &str, &str_len, &outbuf, &signoutlen) == FAILURE) 
		return;

	//pub key
	unsigned char pub1[128];
	unsigned char pub2[3];

	ret = CGet_public_key(pub1, pub2);

	printf("CGet_public_key=%d\n", ret);

	ret = CVerify_dataEx((CK_BYTE_PTR)str, str_len, (CK_BYTE_PTR)outbuf, signoutlen, pub1, pub2);

	printf("CVerify_dataEx=%d\n", ret);

	RETURN_LONG(ret);
}
/* }}} */

/* {{{ proto string CGet_public_key()
    */
PHP_FUNCTION(CGet_public_key)
{
	int ret;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	unsigned char pub1[128];
	unsigned char pub2[3];

	ret = CGet_public_key(pub1, pub2);
	printf("CGet_public_key ret = %d\n", ret);
	PrintHex(pub1, 128);
	PrintHex(pub2, sizeof(pub2));

	RETURN_LONG(ret);
}
/* }}} */

/* {{{ proto int CCreate_client_socket()
   callable callback, string ip, int port) */
PHP_FUNCTION(CCreate_client_socket)
{
	zval* callbak;
	char *ip = NULL;
	int argc = ZEND_NUM_ARGS();
	int ip_len;
	int port;
	int ret;

	if (zend_parse_parameters(argc TSRMLS_CC, "sl",&ip,&ip_len,&port) == FAILURE) 
		return;

	ret = CCreate_client_socket(mycreatebak, ip, port);

	char *data = "1234567890";
	mycreatebak(data,strlen((char *)data));

	printf("CCreate_client_socket ip=%s\n", ip);
	printf("CCreate_client_socket port=%d\n", port);
	printf("CCreate_client_socket ret=%d\n", ret);

	RETURN_LONG(ret);

}
/* }}} */

/* {{{ proto int getSocketStatus()
    */
PHP_FUNCTION(getSocketStatus)
{
	int ret;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	ret = getSocketStatus();

	RETURN_LONG(ret);
}
/* }}} */

/* {{{ proto int CSend_message(string str)
    */
PHP_FUNCTION(CSend_message)
{
	char *str = NULL;
	int argc = ZEND_NUM_ARGS();
	int str_len;
	long len;
	int ret;

	if (zend_parse_parameters(argc TSRMLS_CC, "s", &str, &str_len) == FAILURE) 
		return;

	ret = CSend_message(str, str_len);
	printf("CSend_message ret=%d\n", ret);

	RETURN_LONG(ret);
}
/* }}} */

/* {{{ proto int CGet_post_infoEx()
   callable callback, string str, string api, string ip, int port) */
PHP_FUNCTION(CGet_post_infoEx)
{
	char *str = NULL;
	int argc = ZEND_NUM_ARGS();
	int str_len;
	char *api = NULL;
	char *ip;
	int api_len;
	int ip_len;
	int port;
	int ret;

	if (zend_parse_parameters(argc TSRMLS_CC, "sssl", &str, &str_len, &api, &api_len, &ip, &ip_len, &port) == FAILURE) 
		return;

	ret =  CGet_post_infoEx(mypostbak, str, str_len, api, ip, port);

	char *data = "0987654321";
	mypostbak(data,strlen((char *)data));

	printf("CGet_post_infoEx str=%s\n", str);
	printf("CGet_post_infoEx str_len=%d\n", str_len);
	printf("CGet_post_infoEx ip=%s\n", ip);
	printf("CGet_post_infoEx port=%d\n", port);
	printf("CGet_post_infoEx ret=%d\n", ret);

	RETURN_LONG(ret);
}
/* }}} */

/* {{{ proto int CClose_socket()
   callable callback, string ip, int port) */
PHP_FUNCTION(CClose_socket)
{
	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}
	CClose_socket();
}
/* }}} */

/* {{{ proto int CMd5_dataEx(string str)
    */
PHP_FUNCTION(CMd5_dataEx)
{
	char *str = NULL;
	int argc = ZEND_NUM_ARGS();
	int str_len;

	if (zend_parse_parameters(argc TSRMLS_CC, "s", &str, &str_len) == FAILURE) 
		return;

	unsigned char src[]="abc";

	// MD5校验
	//char* result;
	//result = CMd5_dataEx((char *)src, strlen((char *)src));
	//printf("CMd5_dataEx src=%s,dst=\n", src);
	//PrintHex(result, 16);
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim

部署
=====================================================================

PHP扩展部署非常简单,标准流程
1、/usr/local/m1905/php/bin/phpize
2、./configure –with-php-config=/usr/local/m1905/php/bin/php-config
3、make & make install

vi php.ini
[myfun]
extension = myfun.so

注:如果使用了三方动态库,则需指定动态库所在位置,与config.m4配置吻合
./configure –with-php-config=/usr/local/m1905/php/bin/php-config –with-keys=/usr/local/keys

最后有一个手册 《Extending and Embedding PHP》 推荐看看

附录 PHP扩展标准输入输出
=====================================================================

一些输入的类型:

类型指定符 对应的C类型 描述

  • l long 符号整数
  • d double 浮点数
  • s char *, int 二进制字符串,长度
  • b zend_bool 逻辑型(1或0)
  • r zval * 资源(文件指针,数据库连接等)
  • a zval * 联合数组
  • o zval * 任何类型的对象
  • O zval * 指定类型的对象。需要提供目标对象的类类型
  • z zval * 无任何操作的zval

输出的函数

设置返回值并且结束函数 设置返回值 宏返回类型和参数

  • RETURN_LONG(l) RETVAL_LONG(l) 整数
  • RETURN_BOOL(b) RETVAL_BOOL(b) 布尔数(1或0)
  • RETURN_NULL() RETVAL_NULL() NULL
  • RETURN_DOUBLE(d) RETVAL_DOUBLE(d) 浮点数
  • RETURN_STRING(s, dup) RETVAL_STRING(s, dup) 字符串。如果dup为1,引擎会调用estrdup()重复s,使用拷贝。如果dup为0,就使用s
  • RETURN_STRINGL(s, l, dup) RETVAL_STRINGL(s, l, dup) 长度为l的字符串值。与上一个宏一样,但因为s的长度被指定,所以速度更快。
  • RETURN_TRUE RETVAL_TRUE 返回布尔值true。注意到这个宏没有括号。
  • RETURN_FALSE RETVAL_FALSE 返回布尔值false。注意到这个宏没有括号。
  • RETURN_RESOURCE(r) RETVAL_RESOURCE(r) 资源句柄。

基于Opencv的智能切图

概要

图片裁剪作为网站的核心功能之一,使用非常频繁。大部分情况,我们是按照比例、尺寸进行切割;然实际情况中,我们是希望保留重要区域或者有意义区域给用户。

所以出现了如下PHP扩展,该扩展基于Opencv开发,Opencv在图片模式匹配上较为突出;有一些算法和微调参数,代码量少,易于定制二次开发,目前用于一淘团队的淘客。

除了Opencv外,还有很多图像函数处理库,
如:Imagemagic、CxImage、CImg、FreeImage、Paintlib,有特殊需求可以自己扩展试试。
当然还有PHP自带的GD 库,一般用这个。

功能

1、能进行人脸识别。图片中有人脸,将自动视为人脸区域为重要区域,将不会被裁剪掉。
2、自动识别其它重要区域。如果图片中未识别出人脸,则会根据特征分布计算出重区域。
总而言之,自动识别图片中的重要区域,并且在图片裁剪时保留重要区域。

部署

//基础库
yum install gtk+ gtk+-devel pkgconfig libpng zlib libjpeg libtiff cmake

//opencv
wget http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.4.4/OpenCV-2.4.4a.tar.bz2/download

cmake CMakeLists.txt
make && make install

vi /etc/profile

//unset i 前增加
export PKG_CONFIG_PATH=/usr/lib/pkgconfig/:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH

source /etc/profile
echo “/usr/local/lib/” > /etc/ld.so.conf.d/opencv.conf
ldconfig

===================================================================
//php扩展

git clone https://github.com/exinnet/tclip.git

/usr/bin/phpize
./configure –with-php-config=/usr/bin/php-config
make && make install

vi /etc/php.ini
[tclip]
extension = tclip.so

重启fpm

===================================================================
//使用
tclip(文件原路径,裁剪后的图片保存路径,裁剪后的图片宽度,裁剪后的图片高度)
示例:
$source_file = “/tmp/a.jpg”;
$dest_file = “/www/a_dest.jpg”;
$width = 400;
$height = 200;
tclip($source_file, $dest_file, $width, $height);

===================================================================
安装命令行:
如果想使用命令行方式,可以进行如下安装
1. cd 进入安装包soft文件夹内
2. chmod +x ./tclip.sh
3. ./tclip.sh
4. cp tclip /usr/local/bin/

参数说明:
-s 原图路径
-d 裁剪后的图片保存路径
-w 裁剪后的图片宽度
-h 裁剪后的图片高度

tclip -s x.jpg -d x_dest.jpg -w 200 -h 200

Nfs、Samba、Cifs详解 熟悉的老朋友

简介

三种最常用的共享协议(服务)

1、NFS允许一个系统在网络上与他人共享目录和文件。通过使用NFS,用户和程序可以像访问本地文件一样访问远端系统上的文件。
(场景:用于 *NIX 之间文件的共享,用于小型存储服务或者小型网站)

2、Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。
(场景:用于 *NIX 与 Windows 之间文件的共享,用于小型跨系统服务或者小型公司办公区文件共享)

3、CIFS是公共的或开放的SMB协议版本,并由Microsoft使用。SMB协议现在是局域网上用于服务器文件访问和打印的协议。
(场景:CIFS可以看做是应用程序协议如文件传输协议和超文本传输协议的一个实现)

部署

NFS

//nfs安装
yum install rpcbind nfs-utils nfs-utils-lib nfs-utils-lib-devel

//服务端配置
vi /etc/exports
/data/ftp/uploadfile 192.168.3.201(rw,sync) *(ro)

//服务端启动
service rpcbind start
service nfs start

//服务端开机启动
chkconfig rpcbind on
chkconfig nfs on

//查看可挂载点
showmount -e 192.168.3.203

//客户端挂载 供Nginx使用
mount -t nfs 192.168.3.203:/home/www /data/html/imagecut/uploadfile

Samba

0、确保selinux已经关闭

//关闭 selinux (需重启机器)
vi /etc/selinux/config
SELINUX=disabled

1、安装 server client web管理

//安装
yum install samba samba-client samba-swat

//查看
rpm -qa|grep samba

2、启动
/etc/init.d/smb start

//开机自启
chkconfig –level 35 smb on

3、配置

vi /etc/samba/smb.conf

//简单无密码共享
workgroup = WORKGROUP //定义工作组,也就是windows中的工作组概念
server string = David Samba Server Version %v //定义Samba服务器的简要说明
netbios name = DavidSamba //定义windows中显示出来的计算机名称
log file = /var/log/samba/log.%m //定义Samba用户的日志文件,%m代表客户端主机名
security = share //共享级别,用户不需要账号和密码即可访问

[public] //设置针对的是共享目录个别的设置,只对当前的共享资源起作用
comment = Public Stuff //对共享目录的说明文件,自己可以定义说明信息
path = /home/public //用来指定共享的目录,必选项
public = yes //所有人可查看,等效于guest ok = yes

//更改文件夹权限
chown -R nobody.nobody /home/public
chmod -R 777 /home/public

4、重启服务
/etc/init.d/smb restart

5、windows做磁盘映像

地址:
\\192.168.3.200\public
方法:
我的电脑 ->工具->映射网络驱动器

定制Centos发行版

简介

Centos是Linux发行版之一,它是来自于Red Hat Enterprise Linux依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定性的服务器以CentOS替代商业版的Red Hat Enterprise Linux使用。两者的不同,在于CentOS并不包含封闭源代码软件。

为什么要定制

1、定制与业务相关服务部署
选用特定的软件包,部分软件包需要定制RPM (参考:http://www.wubiao.info/511
2、开发的系统直接集成到操作系统,一键式部署
3、…

如何定制

//轻量级Centos定制发行版
==============================================================================
一、基础

//操作环境:
VM+CentOS-6.4-x86_64-minimal.iso

//基本软件
yum -y install createrepo genisoimage

//VM需设置1个光驱 挂载DVD1
安装centos6.4X 86_64系统,所需组件自行定义,安装后得到install.log和anaconda-ks.cfg文件

//初始目录
mkdir /mnt/cd1 #建立光盘的挂载目录
mount /dev/cdrom /mnt/cd1 #挂载DVD
mkdir -p /root/centos_1905/Packages #建立定制光盘文件目录

二、定制系统文件的准备

新定制系统由以上系统组件包说决定,文件由install.log安装日志得来

vi /root/cp_files.sh

#!/bin/bash
for i in $(awk '/Installing/ {print $2}' install.log)
do
  cp /mnt/cd1/Packages/${i}.rpm /root/centos_1905/Packages
  [ $? != 0 ] && echo "copy ${i} is  faied"
done
rsync -a --exclude=Packages /mnt/cd1/ /root/centos_1905/

三、下载Development Tools相关软件

另找机器,通过yum -y groupinstall “Development Tools”缓存相关软件包

需安装其他基础依赖包,都可通过yum准备相关文件。

//开启缓存
vi /etc/yum.conf
keepcache=1

拷贝相关软件到Packages下
scp /var/cache/yum/x86_64/6/base/packages/* root@192.168.3.227:/root/centos_1905/Packages

四、ks文件准备 (非自动安装忽略此步)

ks文件由系统安装所得anaconda-ks.cfg进行修改所得 (也可用 system-config-kickstart 生成)

vi /root/centos_1905/isolinux/ks.cfg

# Kickstart file automatically generated by anaconda.

#version=DEVEL
install
cdrom
lang en_US.UTF-8
keyboard us
network --onboot no --device eth0 --bootproto dhcp --noipv6
network --onboot no --device eth1 --bootproto dhcp --noipv6
rootpw  --iscrypted $6$ap3J1vcG32p9wu7m$Q4YQJdR4jvxNjhTDNhw0d/qFdcd/TufkoZ3GZ4VZ7fkna3oZEnAYrXAqrBk11b6S6.gAWqsb8.EBAuerI8k/l.
firewall --service=ssh
authconfig --enableshadow --passalgo=sha512
selinux --disabled
timezone --utc Asia/Chongqing
bootloader --location=mbr --driveorder=xvda --append="crashkernel=auto console=hvc0 rhgb quiet"
# The following is the partition information you requested
# Note that any partitions you deleted are not expressed
# here so unless you clear all partitions first, this is
# not guaranteed to work
#clearpart --linux --drives=xvda
#volgroup VolGroup --pesize=4096 pv.202002
#logvol /home --fstype=ext4 --name=lv_home --vgname=VolGroup --grow --size=100
#logvol / --fstype=ext4 --name=lv_root --vgname=VolGroup --grow --size=1024 --maxsize=51200
#logvol swap --name=lv_swap --vgname=VolGroup --grow --size=4000 --maxsize=4000

#part /boot --fstype=ext4 --size=500
#part pv.202002 --grow --size=1

#repo --name="CentOS"  --baseurl=cdrom:xvdd --cost=100

%packages --nobase
@core
%end

五、让系统从kickstart配置启动安装 (非自动安装忽略此步)

vi /root/centos_1905/isolinux/isolinux.cfg

default auto
timeout 600
display boot.msg

menu background splash.jpg
menu title Welcome to CentOS 6.4!
menu color border 0 #ffffffff #00000000
menu color sel 7 #ffffffff #ff000000
menu color title 0 #ffffffff #00000000
menu color tabmsg 0 #ffffffff #00000000
menu color unsel 0 #ffffffff #00000000
menu color hotsel 0 #ff000000 #ffffffff
menu color hotkey 7 #ffffffff #ff000000
menu color scrollbar 0 #ffffffff #00000000

label auto
  menu label ^Auto Install system
  menu default
  kernel vmlinuz
  append ks=cdrom:/isolinux/ks.cfg initrd=initrd.img

label linux
  menu label ^Install or upgrade an existing system
  menu default
  kernel vmlinuz
  append initrd=initrd.img
label vesa
  menu label Install system with ^basic video driver
  kernel vmlinuz
  append initrd=initrd.img xdriver=vesa nomodeset
label rescue
  menu label ^Rescue installed system
  kernel vmlinuz
  append initrd=initrd.img rescue
label local
  menu label Boot from ^local drive
  localboot 0xffff
label memtest86
  menu label ^Memory test
  kernel memtest
  append -

六、重新生成comps.xml

//清空repodata
rm -rf /root/centos_1905/repodata/*

//编辑软件包配置(详见附录)
vi /root/centos_1905/repodata/comps.xml

//生成依赖 comps.xml
createrepo -g /root/centos_1905/repodata/comps.xml /root/centos_1905/

mv /root/centos_1905/repodata/*-comps.xml /root/centos_1905/repodata/comps.xml

cd /root/centos_1905/
declare -x discinfo=$(head -1 .discinfo)
createrepo -u “media://$discinfo” -g /root/centos_1905/repodata/comps.xml /root/centos_1905/

七、ISO文件的生成

mkisofs -o Centos_1905-text-6.4-x86_64-minimal.iso -input-charset utf-8 -b isolinux/isolinux.bin -c isolinux/boot.cat -joliet-long -no-emul-boot -boot-load-size 4 -boot-info-table -R -J -v -V centos_1905 -T /root/centos_1905

八、生成检验
//yum install anaconda

/usr/bin/implantisomd5 /root/Centos_1905_all_6_14-6.4-x86_64-minimal.iso

RPM包制作详解

简介

RPM是RedHat Package Manager(RedHat软件包管理工具)的缩写,这一文件格式名称虽然打上了RedHat的标志,但是其原始设计理念是开放式的,现在包括OpenLinux、S.u.S.E.以及Turbo Linux等Linux的分发版本都有采用,可以算是公认的行业标准了。我们常用的Centos,当然也是可以使用的。

场景

1、方便用户部署安装
2、定制化一些编译参数,方便集群式部署
3、这次是为了定制操作系统里面的基础库
4、…

详解

一、创建普通用户
group add test
user add test -g test

二、基本文件夹
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

–BUILD #编译之前,如解压包后存放的路径
–BUILDROOT #编译后存放的路径
–RPMS #打包完成后rpm包存放的路径
–SOURCES #源包所放置的路径 源程序包中的文件应采用”软件名-版本号”作为上层目录
–SPECS #spec文档放置的路径
–SPRMS #源码rpm包放置的路径

三、编写.rpmmacros 全局宏变量

vi ~/.rpmmacros

%_topdir /home/test/rpmbuild
%_tmppath /home/test/rpmbuild/tmp
%_buildroot /home/test/rpmbuild/BUILDROOT
%_prefix /

四、整理相关文件

cp libmcrypt-2.5.8.tar.gz ~/rpmbuild/SOURCES/

rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
│ └── libmcrypt-2.5.8.tar.gz
├── SPECS
│ └── libmcrypt.spec
├── SRPMS
└── tmp

五、tengine.spec内容
vi ~/rpmbuild/SPECS/libmcrypt.spec

Name:       libmcrypt
Version:    2.5.8
Release:    1
Vendor:     libmcrypt
Summary:    GUN libmcrypt X86_64
License:    GPL
Source:     libmcrypt-2.5.8.tar.gz
Group:      System Enviroment/Daemons
URL:        http://mcrypt.hellug.gr/lib/
Packager:   simplephp@163.com
%description
libmcrypt package

%prep
%setup -q
./configure

make
%install
make DESTDIR=%{buildroot} install

%clean
rm -rf %{buildroot}
make clean

%files
/usr/local/bin/libmcrypt-config
/usr/local/include/mcrypt.h
/usr/local/include/mutils/mcrypt.h
/usr/local/lib/libmcrypt.la
/usr/local/lib/libmcrypt.so
/usr/local/lib/libmcrypt.so.4
/usr/local/lib/libmcrypt.so.4.4.8
/usr/local/man/man3/mcrypt.3
/usr/local/share/aclocal/libmcrypt.m4

%defattr (-,root,root)

六、生成RPM包

//生成包
rpmbuild -ba ~/rpmbuild/SPECS/libmcrypt.spec

-bp #只执行spec的%pre 段(解开源码包并打补丁,即只做准备)
-bc #执行spec的%pre和%build 段(准备并编译)
-bi #执行spec中%pre,%build与%install(准备,编译并安装)
-bl #检查spec中的%file段(查看文件是否齐全)
-ba #建立源码与二进制包(常用)
-bb #只建立二进制包(常用)
-bs #只建立源码包

//快速打包 (mhash-0.9.9.9.tar.gz)
==============================================================================

vi ~/rpmbuild/SPECS/mhash.spec

Name:       mhash
Version:    0.9.9.9
Release:    1
Vendor:     mhash
Summary:    GUN mhash X86_64
License:    GPL
Source:     mhash-0.9.9.9.tar.gz
Group:      System Enviroment/Daemons
URL:        http://mhash.sourceforge.net
Packager:   simplephp@163.com
%description
mhash package

%prep
%setup -q
./configure

make
%install
make DESTDIR=%{buildroot} install

%clean
rm -rf %{buildroot}
make clean

%files
/usr/local/include/mhash.h
/usr/local/include/mutils/mglobal.h
/usr/local/include/mutils/mhash.h
/usr/local/include/mutils/mhash_config.h
/usr/local/include/mutils/mincludes.h
/usr/local/include/mutils/mtypes.h
/usr/local/include/mutils/mutils.h
/usr/local/lib/libmhash.a
/usr/local/lib/libmhash.la
/usr/local/lib/libmhash.so
/usr/local/lib/libmhash.so.2
/usr/local/lib/libmhash.so.2.0.1
/usr/local/share/man/man3/mhash.3

%defattr (-,root,root)

//打包
rpmbuild -ba ~/rpmbuild/SPECS/mhash.spec

//快速打包 (nginx-1.4.5.tar.gz)
==============================================================================

vi ~/rpmbuild/SPECS/nginx.spec

Name:       nginx
Version:    1.4.5
Release:    1
Vendor:     nginx
Summary:    GUN nginx X86_64
License:    GPL
Source:     nginx-1.4.5.tar.gz
Group:      System Enviroment/Daemons
URL:        http://nginx.org
Packager:   simplephp@163.com
%description
nginx package

%prep
%setup -q
./configure --prefix=/usr/local/m1905/nginx --with-http_ssl_module --with-http_gzip_static_module --with-http_sub_module --with-http_dav_module --without-http_geo_module

make
%install
make DESTDIR=%{buildroot} install

%clean
rm -rf %{buildroot}
make clean

%files

%defattr (-,root,root)
/usr/local/m1905/nginx

//打包
rpmbuild -ba ~/rpmbuild/SPECS/nginx.spec