Category: PHP

Linux查看Nginx、Apache、MySQL、PHP的编译参数

软件安装好了,想查看当初编译时的参数,怎么搞?

1、Nginx,可以通过 -V 参数查看Nginx版本及编译参数

/usr/local/nginx/sbin/nginx -V

nginx version: nginx/1.10.2
built by gcc 4.4.6 20110731 (Red Hat 4.4.6-4) (GCC)
configure arguments: --prefix=/usr/local/nginx/ --with-http_image_filter_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_dav_module --with-http_auth_request_module --with-http_secure_link_module --with-http_slice_module --with-http_stub_status_module --with-stream --with-pcre=/usr/local/tools/pcre-8.38 --with-zlib=/usr/local/tools/zlib-1.2.8

2、Apache,编译参数存放在 apache 的 config.nice 文件,前提时,没有做过 make clean

locate config.nice | grep apache | xargs cat

#! /bin/sh
#
# Created by configure

"./configure" \
"--with-apr=/usr/local/apr/" \
"--with-apr-util=/usr/local/apr-util/" \
"--with-pcre=/usr/local/pcre/" \
"ap_cv_void_ptr_lt_long=no" \
"--enable-proxy" \
"--enable-proxy-connect" \
"--enable-proxy-ftp" \
"--enable-proxy-http" \
"--enable-proxy-scgi" \
"--enable-proxy-ajp" \
"--enable-proxy-balancer" \
"$@"

3、MySQL,利用 msyqlbug 工具,查看MySQL信息

VISUAL=vim; export VISUAL; mysqlbug

...
Some paths: /usr/bin/perl /usr/bin/make /usr/bin/gmake /usr/bin/gcc /usr/bin/cc
GCC: Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enab
le-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions
--enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/j
ava-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-mul
tilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.6 20110731 (Red Hat 4.4.6-4) (GCC)
Compilation info (call): CC='/usr/local/gcc-4.3.4/bin/gcc' CFLAGS=' -fPIC -Wall -O3 -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -D
DBUG_OFF -DMY_PTHREAD_FASTMUTEX=1' CXX='/usr/local/gcc-4.3.4/bin/g++' CXXFLAGS=' -fPIC -Wall -Wno-unused-parameter -fno-implicit-templates -fno-exce
ptions -fno-rtti -O3 -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DDBUG_OFF -DMY_PTHREAD_FASTMUTEX=1' LDFLAGS='' ASFLAGS=''
Compilation info (used): CC='/usr/local/gcc-4.3.4/bin/gcc' CFLAGS=' -fPIC -Wall -O3 -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -D
DBUG_OFF -DMY_PTHREAD_FASTMUTEX=1' CXX='/usr/local/gcc-4.3.4/bin/g++' CXXFLAGS=' -fPIC -Wall -Wno-unused-parameter -fno-implicit-templates -fno-exce
ptions -fno-rtti -O3 -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DDBUG_OFF -DMY_PTHREAD_FASTMUTEX=1' LDFLAGS='' ASFLAGS=''
LIBC:
...
...

4、PHP,可以通过 -i 参数可以打印PHP全局变量和安装信息

/usr/bin/php -i | grep configure

Configure Command => './configure' '--prefix=/usr/local/php/' '--enable-fpm' '--enable-opcache' '--enable-inline-optimization' '--with-libxml-dir=/usr/local/libxml2/' '--with-curl=/usr/local/curl/' '--enable-dba' '--with-gd' '--enable-gd-native-ttf' '--enable-gd-jis-conv' '--with-jpeg-dir=/usr/local/jpeg/' '--with-png-dir=/usr/local/libpng/' '--with-zlib-dir=/usr/local/zlib/' '--with-freetype-dir=/usr/local/freetype/' '--with-pcre-regex=/usr/local/pcre/' '--with-pcre-jit' '--with-pcre-dir=/usr/local/pcre/' '--enable-mbstring' '--enable-pcntl' '--enable-soap' '--enable-shmop' '--enable-sockets' '--enable-sysvsem' '--enable-zip' '--enable-mysqlnd' '--with-mysqli=mysqlnd' '--with-pdo-mysql=mysqlnd'

示例浅谈PHP开发手机APP接口,即API开发

API(Application Programming Interface,应用程序接口)架构,已经成为目前互联网产品开发中常见的软件架构模式,并且诞生很多专门API服务的公司,如:聚合数据百度APIStore

作为最流行的服务端语言PHP(PHP: Hypertext Preprocessor),在开发API方面,是很简单且极具优势的
这篇文章写给不太了解PHP开发API接口的开发者

一、先简单回答两个问题

1、PHP 可以开发客户端吗?
答:正确的回答是,不适合,因为PHP是服务端脚本语言,负责 B/S或C/S 架构的S部分,即:Server端的开发。(别去纠结 GTK、WinBinder了)

2、为什么选择 PHP 作为开发服务端的首选?
答:跨平台(可以运行在UNIX、LINUX、WINDOWS、Mac OS下)、低消耗(PHP消耗相当少的系统资源)、运行效率高(相对而言)、MySQL的完美搭档,本身是免费开源的,......

二、如何使用 PHP 开发 API 呢?

有兴趣细研究的,可以先看看百科介绍:
http://baike.baidu.com/item/api/10154

百科写的比较泛,嫌文字多?好吧,那就不看了,先了解下 API 是什么鬼
1、API 比开发 WEB 更简洁,但可能逻辑更复杂,API 只返回结果,也就是只完成数据输出,不呈现页面
2、WEB 开发,更多的是 GET 和 POST 请求,API 还有 PUT、DELETE 请求
3、和 WEB 开发一样,首先需要一些相关的参数,这些参数,都会由客户端传过来,也许是 GET 也许是 POST,这个需要开发团队相互之间约定好,或者制定统一规范
4、有了参数,根据应用需求,完成数据处理,例如:获取用户信息、发朋友圈、发消息、一局游戏结束数据提交等等
5、数据逻辑处理完之后,返回客户端所需要用到的相关数据,例如:用户信息数组、朋友圈列表、消息状态、游戏结果数据等等,那数据是怎么返给客户端呢?常见有XML、JSON,设置相应的header并把要返回的数据直接打印出来即可
6、客户端获取到你返回的数据后,在客户端本地和用户进行交互

所以我们大概知道,API 其实不存在Web领域的 MVC 架构模式,若要分层的,API 也只有 M 和 C 两层,当然,后端可能会有更加复杂的架构!

通过下面一个HTTP协议的API实例来理解PHP怎么开发API:

<?php
/**
 * 比较标准的接口输出函数
 * @param string  $info 消息
 * @param integer $code 接口错误码,很关键的参数
 * @param array   $data 附加数据
 * $param string  $location 重定向
 * @return array
 */
function var_json($info = '', $code = 10000, $data = array(), $location = '') {
    $out['code'] = $code ?: 0;
    $out['info'] = $info ?: ($out['code'] ? 'error' : 'success');
    $out['data'] = $data ?: array();
    $out['location'] = $location;
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($out, JSON_HEX_TAG);
    exit(0);
}

$a = empty($_GET['a']) ? '' : $_GET['a'];
$qq = empty($_GET['qq']) ? 0 : intval($_GET['qq']);

//假设这是数据源,如MySQL
$data = array();
$data[979136] = array('qq'=>979136, 'vip'=>5,'level'=>128, 'reg_time'=>1376523234, 'qb'=>300);
$data[979137] = array('qq'=>979137, 'vip'=>8,'level'=>101, 'reg_time'=>1377123144, 'qb'=>300);

preg_match('/^[a-zA-Z]+$/', $a) || var_json('非法调用');
isset($data[$qq]) || var_json('用户不存在', 100001);

switch ($a) {
    //获取用户基本信息
    case 'info': 
        //你的更多业务逻辑 ...
        var_json('success', 0, $data[$qq]);
        break;
    //获取动态消息
    case 'message':
        var_json('您正在调用动态消息接口', 0);
        break;
    //获取好友列表
    case 'friends':
        var_json('你正在调用好友列表接口', 0);
        break;
    default:
        var_json('非法调用');
}

把它部署到服务器之后,任何语言都可以通过HTTP协议调用诸如下面的URL接口:
http://demo.979137.com/api/test/user.php
http://demo.979137.com/api/test/user.php?a=info&qq=979137&ticket=test
http://demo.979137.com/api/test/user.php?a=info&qq=979138&ticket=test
http://demo.979137.com/api/test/user.php?a=friends&qq=979137&ticket=test
http://demo.979137.com/api/test/user.php?a=fuck&qq=979137&ticket=test

接口输出示例,返回的是一串json:

{
    "code": 0,
    "info": "success",
    "data": {
        "qq": 979137,
        "vip": 8,
        "level": 101,
        "reg_time": 1377123144,
        "qb": 300
    },
    "location": ""
}

json具有很强的跨平台性,几乎每种开发语言都可以直接解析,下面是一个PHP作为客户端调用的示例:

<?php
header('Content-type:text/html;charset=utf-8');
$url = "http://demo.979137.com/api/test/user.php
$arg = array(
    'a'  => 'info',
    'qq' => '979137',
);
$query_string = http_build_query($arg);
$ch = curl_init($url.'?'.$query_string);
curl_setopt($ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_USERAGENT , 'QQ_Mobile_V5.5');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , 60 );
curl_setopt($ch, CURLOPT_TIMEOUT , 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER , true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch , CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false) {
    var_dump(curl_error($ch));
} elseif ($httpcode != 200) {
    var_dump($httpcode, '接口请求失败');
} else {
    $ret = json_decode($response, true);
    var_dump($ret);
}

页面输出结果:

array(4) {
    [“code”]=>int(0)
    [“info”]=>string(7) “success”
    [“data”]=>
    array(5) {
        [“qq”]=>int(979137)
        [“vip”]=>int(8)
        [“level”]=>int(101)
        [“reg_time”]=>int(1377123144)
        [“qb”]=>int(300)
    }
    [“location”]=>string(0) “”
}

实际业务中,就是拿到了接口返回的数据之后,结合自身的业务为用户提供服务!

三、实际项目中,我们在开发 API 时应该注意的几个点(仅供参考)

1、单文件实现多接口的形式有很多种,例如:if..elseif.. 或 switch 或 很多框架里用到的统一入口通过调用类函数体
2、数据输出建议使用json,json具有很强的跨平台性,大多编程语言都支持json解析,json正在逐步取代xml,成为网络数据的通用格式
3、为了保证接口安全,一定要加入鉴权体系
4、对于线上的API,务必关闭所有错误显示同时把错误写到日志里,PHP中可以通过 error_reporting(0) 屏蔽所有错误
这样做的目的,一方面是保护接口安全,防止输出不该打印的错误信息
另一方面是保证输出的是正确的数据格式,如json,假如不是标准的json格式,客户端在解析时就会出错,由此影响客户端的正常运转
PS:我们平时在使用手机APP时,手机会闪退,多半是这个原因,即接口调用异常
5、开发 API 和 WEB 有一定的区别,如果是 WEB 的话,如果程序写的有问题,比如有个notice 或 warning 级别的错误,在 WEB 里可能不会有什么问题,也许就只是导致 WEB 的某个部分错位或乱码。但如果是 API,就会严重调用的客户端了,如果是手机APP,那闪推啥的,是必然的,如果同样也是Web调用,也可能会出现 Server Error 了
6、一定要重点考虑稳定性和响应速度,因为我们在使用手机APP时,都不希望APP经常闪推、而且希望应用很流畅

话说,牛逼的架构,一般都有自己的 API 框架!

这里给 ThinkPHP 打个广告:
目前 ThinkPHP 5ThinkPHP 家族的一个颠覆性重构版本,Slogan:为 API 而生

再扯一下腾讯、微博、淘宝等这些个开放平台吧,
它们所谓的开放,其实就是给开发者提供一系列的API,开发者根据他们提供的技术文档,按规定的调用方法,调它们提供的接口,你就可以获取到他们的相关信息,
例如:QQ用户基本信息、微博登录、淘宝店铺、商品消息等等。然后开发者再根据这些数据,在你的应用里完成交互。
另外,我们常用的 Ajax 其实也是 API 调用的一种体现形式

所有PHP脚本自动包含文件

先看三个典型的应用场景:
1、一台专用于跑定时任务服务器,可能包含了N个项目,每个项目又包含了N个定时任务,每个任务,都依赖某些数据库配置,常规做法都是在每个任务上用require或include或注册自动函数去加载这些文件
2、复杂的后台架构,都会用到中间层,中间层除了逻辑本身,还承担了接口转发的工作,如果你的项目涉及N个组件的N个REST接口,常规做法一般是写一个配置文件,配置他们的映射关系,然后由中间层去读取这个配置
3、一个研发团队,往往都有自己的公共组件、公共类库、函数库,可能是自己开发的也可能第三方的,当开发者需要用到这些公共组件或类库时,常规做法就是拷贝到自己工程目录内,

这里有个共同的问题就是需要手工去加载公共配置文件,那么有没有一个不需要手工加载,让你的每个脚本在编译的时候就自动的包含这些文件呢?

必然是有的,PHP有两个重要的配置

  • auto_prepend_file 自动的在你的PHP脚本前包含文件
  • auto_append_file 自动的在你的PHP脚本前包含文件

例如:

auto_prepend_file = "/service/auto_include.php"
auto_append_file = "/service/footer.php"

这样就相当于你所有的PHP脚本都拥有了 auto_include.php、footer.php 的代码

你可以将数据库配置信息统一定义 auto_include.php,这样你整台服务器的PHP都能用统一的数据库信息了,一单需要修改(如数据库密码、端口号等)只要改这一个文件即可;
您也可以定义好想要的各种类库,然后统一包含在 auto_include.php,这样你便可以在任何地方使用到自己的底层类库了。

用过新浪云SAE的人应该知道,在SAE环境内,你可以使用很多SAE官方提供的云服务如KVDB、Stroage、FetchURL、...)对应的类库或者接口,这些服务,并不是PHP扩展,而是SAE官方预先写好的服务,在通过auto_prepend_file加载到用户的脚本里

附:

如果使用的是Apache,还可以对单个目录进行不同配置选项的修改。这样做的前提是服务器允许重设其主配置文件。要给目录设定自动前加入和自动追加,需要在该目录中创建一个名为 .htaccess 的文件。这个文件需要包含如下两行代码:

php_value auto_prepend_file "/service/auto_include.php"
php_value auto_append_file "/service/footer.php"

注意:
其语法与配置文件php.ini中的相应选项有所不同,和行开始处的php_value一样:没有等号。
许多php.ini中的配置设定也可以按这种方法进行修改。
在 .htaccess 中设置选项,而不是php.ini中 或是在Web服务器的配置文件中进行设置,将带来极大的灵活性。
可以在一台只影响你的目录的共享机器上进行。
不需要重新启动服务器而且不需要管理员权限。
使用 .htaccess 方法的一个缺点就是目录中每个被读取和被解析的文件每次都要进行处理,而不是只在启动时处理一次,所以性能会有所降低。

实际应用

简单实用的PHPMonitor:运行错误监控

PHP,CURL和你的安全!

如果最近你在美国看电视,你会经常看到一个这样的广告:

一个和蔼友善的家伙说“我希望我的电脑被病毒感染”,
“我希望所有我家的照片都被人删除,找不回来。”

“我希望我的笔记本运转的声音听起来像打雷。”

当然,没有一个正常人希望遇到这样的痛苦,但如果你不对自己的电脑采取保护措施,结果就是让黑客得逞。
你需要理解,这就像在你家里,车或钱袋子,你不能让它们都敞着口放在外面,你不能认为陌生路人都是可信的。
大部分的陌生人并不像你想象的那样友好。

如果没有人告诉你应该怎么做,你很容易犯错误。置之不理是愚蠢的,幸好你读了这篇文章。我要首先假设你不是那么愚蠢的人。

不应该做的事情

下面是一个列表,解释了什么不该做,以及为什么。

这是外表美味可口巧克力,里面却藏着恶魔。它的意思是

去 www.webhek.com 网站,取回页面内容,运行这些内容,不论是什么内容。

如果是像下面的这些内容到无所谓:

Hello World

但是,如果你不那么幸运,这个网站被人动过手脚,它的内容被替换成:

Evil ruuLzzzzorz!!!

这句代码会删除你的电脑上的所有东西。

这样会稍微安全一些,因为这句代码的做法是读取远程页面的内容,然后打印它们。即使有人在内容里插入了恶意的PHP代码,这些代码也没有机会被执行。
但是,黑客仍然可以在内容里注入恶意的 JavaScript,你会发现你的页面上突然间被植入了无数的弹出式广告窗口页面。
这会让你的网站的浏览者非常恼怒。这里面有很多的学问,但上面这些是最大的问题。

应该如何做

PHP里面有一个非常强大的函数库,它们的目的就是让你安全的从远程网站上取回内容。
这些函数被称作CURL。现在,你不要被CURL官方页面上大量的东西吓阻,它实际上非常的简单。

下面是一个简单的替换上面read_file()命令的做法:

<?php
$curl_handle=curl_init();
curl_setopt($curl_handle,CURLOPT_URL,'http://www.webhek.com');
curl_exec($curl_handle);
curl_close($curl_handle);

就是这样,这才是你应该做的,最后一句 curl_close() 不是必要的。

小心,你仍然有被远程网站上的恶意 JavaScript 和 cookie 盗取者袭击的风险。
防范这些攻击需要牵涉到更多的内容。如果你想做这些,我建议你使用PHP正则表达式函数里的 preg_replace()。

假设我们确实要用CURL来做一些事情。假设 www.webhek.com 这个网站不是那么稳定。它有时候会没有响应,一个页面需要30秒才能拉取成功。对于这种情况,我们的办法是:

<?php
$curl_handle=curl_init();
curl_setopt($curl_handle,CURLOPT_URL,'http://www.webhek.com');
curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
curl_exec($curl_handle);
curl_close($curl_handle);

这种写法是说,2秒钟内如果不能抓取完数据就做超时处理。
是的,也许你更愿意设定为1秒就算超时,因为它妨碍你的页面的速度。(注意,不要设置为0,这是告诉curl没有超时限制。)

但是,如果是什么东西都没有取回了,你想显示一个提示信息,这该怎么办?哈哈,简单!

<?php
$curl_handle=curl_init();
curl_setopt($curl_handle,CURLOPT_URL,'http://www.webhek.com');
curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
$buffer = curl_exec($curl_handle);
curl_close($curl_handle);

if (empty($buffer)) {
    print "抱歉,webhek.com 这个网站又无响应了。<p>";
} else {
    print $buffer;
}

微信公众号:程序员到架构师

最新文章

Return Top