nginx+php出现No input file specified解决办法

今天在自己本地的开发环境突然出现了No input file specified错误,反复检查返现自己的配置文件和配置路径以及权限都没有问题。经过反复的排查终于发现了问题,现将问题及解决分享如下:

问题原因分析

在GitHub上下载了一个开源的tp5项目,之前自己本地的网站运行都没有问题。但是安装了这个开源项目后就发现本地其他网站都无法访问了。访问就是No input file specified错误。在网上也找了解决办法,但是都不是,看来这个错误有点儿诡异。
后来反复尝试,重启电脑后问题得到解决但是再次运行下载的tp5开源项目后其他网站又出现了这样的错误No input file specified 而且只有这一个网站运行没有问题。
据此将错误圈定在该开源项目的nginx配置文件中。再来看看该配置文件:

server {
    listen 80;
    server_name local.test.com;
    access_log /data/wwwlogs/local.test.com.log combined;
    error_log /data/wwwlogs/local.test.com_error.log error;
    index index.html index.htm index.php;
    root /data/php/test;

    add_header X-Powered-Host $hostname;
    fastcgi_hide_header X-Powered-By;

    if (!-e $request_filename) {
        rewrite  ^/(.+?\.php)/?(.*)$  /$1/$2  last;
        rewrite  ^/(.*)$  /index.php/$1  last;
    }

    location ~ \.php($|/){
        fastcgi_index   index.php;
        fastcgi_pass    127.0.0.1:9000;
        include         fastcgi_params;
        set $real_script_name $fastcgi_script_name;
        if ($real_script_name ~ "^(.+?\.php)(/.+)$") {
            set $real_script_name $1;
        }
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param SCRIPT_NAME $real_script_name;
        fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
        fastcgi_param PHP_VALUE       open_basedir=$document_root:/tmp/:/proc/;
    }

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
        access_log  off;
        error_log   off;
        expires     30d;
    }

    location ~ .*\.(js|css)?$ {
        access_log   off;
        error_log    off;
        expires      12h;
    }

在以上的配置中其他都是常规的配置。因为我使用cgi。在fastcgi参数中有一行可能大家也注意到了。

fastcgi_param PHP_VALUE open_basedir=$document_root:/tmp/:/proc/;

就是这句。这句的主要作用是设置fastcgi的可操作目录从而防止跨站的,将open_basedir限定在了本项目的目录和/tmp/以及/proc/中。

问题解决

刚刚说了是在配置的fastcgi配置中多了一句防止跨站的语句。那么这句话他其实是影响了整个fastcgi的参数,这样因为我的其他网站的路径是/data/php/xxx/这样的目录,而不在本开源项目的目录/data/php/test/所以fastcgi就无法找到。
所以在这句之前加#注释这句或者删除这句重启系统或重启nginx就可以了。

线上部署的建议

那么到底要不要使用这句呢?在线上环境中当然是可以的。在线上项目部署中对于open_basedir中最好别使用$document_root这样的变量。如果有多个项目在线上服务器中那么可以把所以项目放置在一个统一的目录中。例如我的线上是wwwroot目录下放置其他网站。例如/wwwroot/test1 /wwwroot/test2那么我可以配置为

fastcgi_param PHP_VALUE open_basedir=/wwwroot/:/tmp/:/proc/;

nginx+php-fpm访问报错,显示access denied

nginx+php-fpm访问报错,只显示access denied

nginx.conf中root是配置在server段内,“location /”之外,所以排除此错误可能性;

php-fpm中security.limit_extensions也不限制“.php”,所以排除此可能性;

最后,修改了php.ini,将cgi.fix_pathinfo从0改为1,问题解决

CI框架表单验证 is_unique 的一点bug

问题:

is_unique 方法在编辑更新的时候验证会包含当前记录,这是CI框架的一个bug,需要修改Form_validation.php is_unique 方法:

public function is_unique($str, $field)
   {
        if(isset($_POST['id'])){
            $id = $_POST['id'];
        }elseif(isset($_GET['id'])){
            $id = $_GET['id'];
        }
        list($table, $field)=explode('.', $field);
        $this->CI->db->from($table);
        $this->CI->db->limit(1);
        $this->CI->db->where($field,$str);
        if(isset($id)){
            $this->CI->db->where('id !=', $id);
        }
        $query = $this->CI->db->get();
        return $query->num_rows() === 0;
    }

CodeIgniter在nginx下404 not found

今天遇到一个问题:将CI框架写的项目移植到nginx时,发现所有控制器的访问都是404,经过一番资料查找后发现,是nginx配置的问题,正确的如下所示:

server { 

 server_name vm.project.com; 

 location / { 

 index index.html index.php; 

 root /home/www/project; 

 } 

 location ~ \.php($|/) { 

 root /home/www/project; 

 fastcgi_pass unix:/tmp/php-cgi.sock; 

 fastcgi_index index.php; 
 fastcgi_split_path_info ^(.+\.php)(.*)$;
 fastcgi_param PATH_INFO $fastcgi_path_info;

 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
 include fastcgi_params; 
 }
 if (!-e $request_filename) {
 rewrite ^/php_box/(.*)$ /php_box/index.php/$1 last; 
 break;
 } 
}

需要注意的地方:

 location ~ \.php($|/) {

一开始我的配置为:
 location ~ \.php$ { 所以一直没有搞成功,这个问题折腾了很久,特此说明一下。

Apache配置虚拟主机后,不能访问localhost的问题

先说配置虚拟主机的流程:

1.先打开httpd.conf文件,打开httpd-vhosts.conf

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

2.然后打开httpd-vhosts.conf文件,配置一个虚拟主机

<VirtualHost *:80>
    DocumentRoot "D:/amp/www/wechat"
    ServerName www.wechat.com
</VirtualHost>

3.打开hosts文件,添加域名

127.0.0.1        www.wechat.com

4.重启Apache,这时虚拟主机的域名www.wechat.com可以正常访问,

但是我的localhost就不能访问了。报错如下:

 

解决过程:

我的思路是,添加一个名为localhost的虚拟主机不就可以了?

1.打开httpd-vhosts.conf文件,配置一个名为localhost的虚拟主机:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "D:/amp/www"
</VirtualHost>

2.打开hosts文件,添加域名

注意:这一步,做或者不做,都没有影响,亲测通过。

#127.0.0.1        localhost

3.重启Apache,期待的结果并没有出现,哎,都累得半死了,还是不能访问localhost,虽然其他虚拟域名都可以正常访问,

可是我就是想鱼和熊掌兼得,继续查找问题

 

问题解决:

最后我比对了我原来的配置代码,发现,在httpd.conf文件中有一行代码是需要注释掉的

#ServerName localhost:80

就是这一行代码,把我折腾的够呛,把 ServerName 这一行代码注释掉就可以了

也许你的httpd.conf文件中并不是localhost:80 这个值,可能是  ServerName  a.com:80 ; 都一样,直接注释掉

以后无论开启或者关闭虚拟主机,localhost都可以正常访问。

可恶的bug

昨天用了一个表单验证的js插件:Validform,遇到一个奇葩的问题,让我苦恼了好几个小时,用断点调试进行寻找bug,后来有将代码复制到新页面,把无关的代码删除,才找到了bug出现的原因,原来是有个作用的div的id名重复了,导致插件失效,主要是$this->load_template(‘slide.php’);另外加载的模板页跟当前页的id冲突了,不容易发现,这个bug真可恶,让我纠结了好几个小时!!!

奇葩问题解决的原则

1.首先心理上承认程序是有问题的;

2.断点调试,测试各个可能出现问题的环节;

3.不要在上线的项目中测,要新建一个测试页,测试通过后再修改线上的版本;

4.可以去网上查查别人有没有遇到类似的情况,进行借鉴;

5.如果一个问题纠结了半个小时都没有解决,则就要向他人求助,实在不行,则暂且放一放,或许过段时间再看,就知道怎么解决了,不能在一棵树上吊死,记住:时间是宝贵的!

6.有时,用一些第三方的插件在ubuntu下老出现一些奇葩的问题,但是在windows下是正常的,此时就不能在ubuntu上死抠,要换一种思路,去windows上试试!以免浪费时间!

json格式转数组注意事项

今天遇到一个特别奇葩的问题,json格式明明是正确的,转数组时却就是出不来,后来才发现是文件的编码问题,文件的编码一定要是utf-8无BOM格式,这点一定要切记!切记!

如果想确认json是否正确http://www.kjson.com/

json格式的城市:

<?php
$json = '{
 "北京": {
 "key": 11,
 "defaultvalue": 1,
 "values": {
 "东城区": 1,
 "西城区": 2,
 "崇文区": 3,
 "宣武区": 4,
 "朝阳区": 5,
 "丰台区": 6,
 "石景山区": 7,
 "海淀区": 8,
 "门头沟区": 9,
 "房山区": 11,
 "通州区": 12,
 "顺义区": 13,
 "昌平区": 14,
 "大兴区": 15,
 "怀柔区": 16,
 "平谷区": 17,
 "密云县": 28,
 "延庆县": 29  //注意:此处不能有逗号,否则会出错
 }
 }
}';
print_r(json_decode($json,true));//第二个参数true表示强制转成数组

注意事项:json_decode($json,true)中$json的编码必须是utf-8,不是的要用 iconv(‘GB2312’, ‘UTF-8’, $json)转换。