No input file specified ошибка php

The No input file specified is a message you are presented with because of the implementation of PHP on your server, which in this case indicates a CGI implementation (can be verified with phpinfo()).

Now, to properly explain this, you need to have some basic understanding on how your system works with URL’s. Based on your .htaccess file, it seems that your CMS expects the URL to passed along as a PATH_INFO variable. CGI and FastCGI implementations do not have PATH_INFO available, so when trying to pass the URI along, PHP fails with that message.

We need to find an alternative.

One option is to try and fix this. Looking into the documentation for core php.ini directives you can see that you can change the workings for your implementation. Although, GoDaddy probably won’t allow you to change PHP settings on a shared enviroment.

We need to find an alternative to modifying PHP settings
Looking into system/uri.php on line 40, you will see that the CMS attempts two types of URI detection — the first being PATH_INFO, which we just learned won’t work — the other being the REQUEST_URI.

This should basically, be enough — but the parsing of the URI passed, will cause you more trouble, as the URI, which you could pass to REQUEST_URI variable, forces parse_url() to only return the URL path — which basically puts you back to zero.

Now, there’s actually only one possibilty left — and that’s changing the core of the CMS. The URI detection part is insufficient.

Add QUERY_STRING to the array on line 40 as the first element in system/uri.php and change your .htaccess to look like this:

RewriteEngine On 

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 

RewriteRule ^(.*)$ index.php?/$1 [L]

This will pass the URI you request to index.php as QUERY_STRING and have the URI detection to find it.

This, on the other hand, makes it impossible to update the CMS without changing core files till this have been fixed. That sucks…

Need a better option?
Find a better CMS.

Всем привет!

Установил nginx+php-fpm, но когда файла php не существует, nginx отдает ошибку No input file specified. А как убрать ее и заменить на обычную ошибку 404?

Всем спасибо!


  • Вопрос задан

    более трёх лет назад

  • 22268 просмотров

Пригласить эксперта

Причин появления ошибки No input file specified несколько:
1. У вас не установлена переменная SCRIPT_FILENAME в конфиге nginx;
2. Задан неправильный аргумент root в конфиге nginx;
3. Переменная open_basedir в /etc/php5/fpm/php.ini или в конфиге php5-fpm пула содержит путь, который не соответствует аргументу root в конфиге nginx;
4. Пользователь с правами которого работает php5-fpm или конкретный пул php5-fpm не имеет прав доступа к каталогу или файлу с php-скриптом;

Пример правильного конфига nginx + php5-fpm:

server {
....
root /var/www/mysite.com;
index index.php index.html index.htm;

location / {
        try_files $uri $uri/ =404;
}
location ~ .php$ {
        try_files $uri = 404;
        fastcgi_pass unix:/var/lib/php5-fpm/mysite.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
}
...
}

php.ini
cgi.fix_pathinfo = 0


  • Показать ещё
    Загружается…

22 июн. 2023, в 00:59

8000 руб./за проект

22 июн. 2023, в 00:56

8000 руб./за проект

22 июн. 2023, в 00:39

12000 руб./за проект

Минуточку внимания

“No input file specified” or “Primary script unknown” in the error log is one of the most frequently encountered issues in nginx+PHP.

People on serverfault and in the #nginx IRC channel asks for help with this so often that this post is mostly to allow me to be lazy and not have to type up the same answer every time.

This is actually an error from PHP and due to display_errors being 0ff people will often just get a blank page with no output. In a typical setup PHP will then send the error to stderr or stdout and nginx will pick up on it and log it in the nginx error log file. Thus people spend a ton of time trying to figure out why nginx isn’t working.

The root cause of the error is that PHP cannot find the file nginx is telling it to look for, and there are a few common cases that causes this.

Wrong Path Sent to PHP

The most common reason at the time of writing happens because a user uses a horrible tutorial found via google instead of actually understanding nginx. Reading my nginx primer will equip you to actually solve this on your own but since this post is actually dedicated to the error I’ll cheat this once and allow you to be lazy by just giving you the full solution.

Nginx tells PHP about the file to execute via the SCRIPT_FILENAME fastcgi_param value. Most examples in the wiki should define this as $document_root$fastcgi_script_name. The horrible tutorials will often hard code the path value but this is not desirable as we don’t want to duplicate information and invite future screw ups. So you’ve gone with the $document_root$fastcgi_script_name option and suddenly it’s no longer working.

This happens because nginx has 3 levels of inheritance commonly referred to as blocks, these being http, server and location, each being a sub-block of the parent. Directives in nginx inherit downwards but never up or across, so if you define something in one location block it will never be applied in any other location block under any circumstance.

Typically users define their index and root directive in location / because a tutorial told them to. So when they then define SCRIPT_FILENAME using $document_root the root directive is not actually defined and thus the SCRIPT_FILENAME value becomes just the URI making PHP look at the root server dir.

The simple solution here is to just define the directive in your server block. (or http block even!) Generally the higher up your can define a directive the less duplicate directives you’ll need.

Incorrect File Permissions

Most people don’t really believe me when I tell them their file permissions are incorrect. They’re looking at the damn permissions and the PHP user can read the file just fine! Sadly, this shows a lack of understanding of Unix user permissions. Being able to read a file is not enough, a user must also be able to traverse to the file.

This effectively means that not only should the file have read permission, but the entire directory structure should have execute permission so that the PHP user can traverse the path. An example of this:

Say you have an index.php file in /var/www. /var/www/index.php must have read permission and both /var and /var/www must have execute permissions.

Using Alias and $document_root

It is fairly common to define SCRIPT_FILENAME as $document_root$fastcgi_script_filename; However, $document_root does not account for the alias directive and will thus result in an incorrect path being sent. It is preferable to define SCRIPT_FILENAME as such:

fastcgi_param SCRIPT_FILENAME $request_filename;

This accounts for alias and ensures proper path is sent. One note about this is that $request_filename does not account for fastcgi_index, but you only use this index if you send a request ending in / to PHP. If you use the standard PHP location ~ .php$ then you will never use the fastcgi_index directive.

Chrooted Environment

If your PHP lives in a chrooted environment that nginx does not, then they basically have 2 different roots and the file path that nginx reports to PHP will not resolve to the actual file. A simple example to make this obvious:

Lets say you request phpinfo.php, nginx looks in your defined root and finds this file in: /home/user/public_html/phpinfo.php
The PHP process for user is chrooted to only have access to his directory for security reasons, so as far as PHP knows the root of the server is at /home/user. Therefore when nginx reports the file path PHP will look in: /home/user/home/user/public_html/phpinfo.php.

Either make sure both nginx and PHP has the same chroot or make sure you rewrite your internal URI before you fastcgi pass to PHP.

Open Basedir Restriction

PHP has the option to limit file access to certain directories defined in your php.ini. Some distributions might preconfigure this option for their packaging system.

SCRIPT_NAME Versus SCRIPT_FILENAME

Fastcgi has two parameters which are quite similiar in name, make sure that you’re not confusing the SCRIPT_NAME variable for the SCRIPT_FILENAME one. SCRIPT_FILENAME tells fastcgi the location of the script to execute while SCRIPT_NAME merely tells the name of the script.

If you are using nginx with php-cgi and have followed the standard procedure to set it up, you might often get the “No input file specified” error. This error basically occurs when the php-cgi daemon cannot find a .php file to execute using the SCRIPT_FILENAME parameter that was supplied to it. I’ll discuss about the common causes of the error and it’s solutions.

Wrong path is sent to the php-cgi daemon

More often than not, a wrong path (SCRIPT_FILENAME) is sent to the fastCGI daemon. In many of the cases, this is due to a misconfiguration. Some of the setups I have seen are configured like this :

server {
    listen   [::]:80;
    server_name  example.com www.example.com;
    access_log  /var/www/logs/example.com.access.log;  

    location / {
        root   /var/www/example.com;
        index  index.html index.htm index.pl;
    }

    location /images {
        autoindex on;
    }

    location ~ .php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/example.com$fastcgi_script_name;
        include fastcgi_params;
    }
}

Now, there are many things wrong with this configuration. An obvious and glaring issue is the root directive in the location / block. When the root is defined inside the location block, it is available/defined for that block only. Here, the location /images block will not match for any request because it does not have any $document _root defined and we will have to redundantly define root again for it. Obviously, the root directive should be moved out of the location / block and defined in the server block. This way, the location blocks will inherit the value defined in the parental server block. Of course, if you want to define a different $document_root for a location, you can put a root directive in a location block.

Another issue is that the value of the fastCGI parameter SCRIPT_FILENAME is hard-coded. If we change the value of the root directive and move our files somewhere else in the directory chain, php-cgi will return a “No input file specified” error because will not be able to find the file in the hard-coded location which didn’t change when the $document_root was changed. So, we should set SCRIPT_FILENAME as below :

fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

We should keep in mind that the root directive should be in the server block or else, only the $fastcgi_script_name will get passed as the SCRIPT_FILENAME and we will get the “No input file specified” error.

The file actually does not exist

What happens here is that, even when Nginx receives the request to serve a non-existent file with a .php extension, it passes the request to php-cgi. This happens because Nginx does not check for the file, it only checks if the REQUEST_URI ends with a .php. Php-cgi, while trying to processs the request, finds that the php file does not exist at all. Hence it sends a “No input file specified” message with a “404 Not Found” header.

We can intercept the request for the non-existent php file and show a 404 page.

First, find out the version of nginx you are using.

nginx -v

You’ll get an output like this :

nginx version: nginx/0.7.67

If php-cgi is running on port 9000, you’ll have something like this in your
vhosts file :

location ~ .php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME ....
    ...................................
    ...................................
}

Since nginx versions less than 0.6.36 doesn’t have the try_files directive,
we’ll have two versions of the code.

For nginx 0.6.36+

We’ll use try_files here to catch non-existent URLs and display an error page.

location ~ .php$ {
    try_files  $uri =404;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME ....
    ...................................
    ...................................
}

Here we are checking for the existence of the .php file before passing it to the fastCGI backend. If the file does not exist, we return a 404 Not Found page.

For older versions :

location ~ .php$ {
    fastcgi_intercept_errors on;
    error_page  404  /path/to/404.htm;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME ....
    ...................................
    ...................................
}

Here the fastcgi_intercept_errors asks the fastCGI backend to return error statuses to Nginx so that Nginx can respond with a custm 404 page. The error_page directive defines a custom 404 page. Note that this will work for both older and newer versions of Nginx, but personally I think the try_catch method is cleaner.

Permissions are not set correctly

Permissions are not supposed to be much of a headache for executing PHP files. Apparently, we only need to make sure that the user the fastCGI backend is running as, has read permissions for the file. But it is often overlooked that a user also needs execute permissions for every parent directory of a file to chdir to that file. For example, say a file is located at —

/home/steve/files/req.txt

The user needs to have read permissions for the file as well as execute permissions for /, /home, /home/steve and /home/steve/files.

I have covered most of the common issues that cause this error. If you have something else, feel free to leave a comment.

We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.

Active subscription is required.

NGINX <-> PHP-FPM essentials

When you configure NGINX against PHP-FPM, what you really do is teach NGINX where is PHP-FPM listening and what kind of information has to be delivered to it.

NGINX does not do any processing of PHP scripts of its own. It merely talks to PHP-FPM and says:

“Hey PHP-FPM, please run </path/to/this.php> and tell me what you see”.

This couple works well together. On a website with SEO-friendly URLs, NGINX does the job of rewriting request URL in order to construct and pass the proper filename to PHP-FPM. And PHP-FPM does the heavy lifting of parsing the script, running it and delivers resulting HTML back to NGINX.

In general, aside from some extra bits of information like environment variables, NGINX delivers one important piece of information to PHP-FPM – the filename of the script.

The standard bit of configuration illustrates it:

location ~ .php$ {
    # where is PHP-FPM listening? the socket 
    fastcgi_pass unix:/path/to/php-fpm.sock;
    # everytime we're in this location, tell PHP-FPM the complete script filename to be executed
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # <========
    # and don't forget to tell PHP-FPM stuff like SERVER_NAME: 
    include fastcgi_params;

NGINX does not even need to have read access to the .php file in question in order to have it properly launched via PHP-FPM and then displayed to clients.

So this chmod in your site setup may be perfectly valid:

-- site
----- index.php (chmod 0400, chown user:user)
----- style.css (chmod 0640, chown user:nginx)

Note how NGINX has no access for index.php whatsoever, yet the page will work just fine in our setup.

Let’s expand to another case, our case of interest for this post.

What would happen when someone visits a non-existent .php file? NGINX will happily pass it along to PHP-FPM as usual, and PHP-FPM will return the dreaded:

No input file specified.

This error is emitted by NGINX to the client’s browser. Because that’s what PHP-FPM happens to produce when you give it a filename that doesn’t exist.

Well, it’s a 404 error. Why bother? Sure enough, that’s not really the kind of error you want your users to see.

So in this post, I will tell you what are the dos and don’ts in fixing this error. That is, aside from obvious misconfiguration you might have.

Our case is when the script file is really not there. In other words, let’s see what is the best configuration approach to handling 404s for requests to missing .php files. And showing something better looking than No input file specified.

Solution on the PHP-FPM side? None that I know

There’s no way to customize the message. Well, in theory, you can patch and recompile PHP like those poor folks who like to play with NGINX compilation.

So let’s move on to NGINX. There are multiple ways to solve it there, and I tell you this – there are too many ways to do things inherently wrong. Use the power that NGINX gives you wisely.

Solutions in NGINX

Going down from worst to best.

Worst

You may have seen this one:

location ~ .php$ {
    if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
    ...
    fastcgi_pass unix:/path/to/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;

The idea is to check if .php script is really there, then rewrite to /index.php, which is supposed to know how to display 404 nicely (some CMS framework). Cute, nah?

You know why it’s already bad: if is evil. We all already know that blah blah.. Give me a break 🙂

But what would happen if we retain our very secure chmod (0400 on .php files) that we began our post with? We’ll get error upon accessing any .php file:

rewrite or internal redirection cycle while internally redirecting to “/index.php

Here’s why. When NGINX receives request for /some.php, it takes us to our location ~ .php$ {. From there it checks the file for existence. And since it doesn’t have any access to it whatsoever, it will rewrite it to /index.php in order to handle 404, then go in the same location ~ .php$ {., and check index.php for existence, and get stuck in a loop.

All simply because it has no access for .php files.

Come on, just let NGINX read the .php files. It’s OK. Just let it be.

Well, I don’t want to if I can. There is never enough security. And secure chmod is something essential. Let’s keep trying.

So how about …

location ~ .php$ {
    try_files  $uri =404;
    ...
    fastcgi_pass unix:/path/to/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;

That’s cuter. No ifs, just try_files. All as per NGINX ninja style. But wait, how about having the error page displayed by your PHP framework? Doable also with:

location ~ .php$ {
    try_files  $uri /index.php =404;
    ...
    fastcgi_pass unix:/path/to/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;

Stop right there. We’re still letting NGINX check file for existence, so it’s still going to fail if it has no access to the scripts in our secure setup.

So what to do?

Best solution

location = /404.php {
    fastcgi_intercept_errors off;

    fastcgi_pass unix:/path/to/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    ...
}
location ~ .php$ {
    error_page 404 /404.php;
    fastcgi_intercept_errors on;

    fastcgi_pass unix:/path/to/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    ...
}

I owe you some explanation, right? In our location ~ .php$ { we tell NGINX, that when it sees PHP-FPM giving it a 404 HTTP status in the response, it can handle it on its own way. That is, discarding the HTML we get from PHP-FPM and using something else. But what?

We tell NGINX what page to display upon receiving 404 from PHP-FPM, here: error_page 404 /404.php;.

We have to set up a dedicated location for /404.php because we know this script exists (you have to create it, of course, if your framework has none; and it must be different from the front page handler like index.php). We don’t want to discard PHP-FPM output for it, so we put fastcgi_intercept_errors off;. Which is the default, so can be omitted but kept for illustration of what happens there.

Now NGINX doesn’t need to check for script existence. PHP-FPM will be the one to tell it.

So there you have it: a clean, tidy solution to 404 pages on missing .php script files in NGINX. It’s also secure and allows for lockdown chmod.

  • No ide master hdd detected press f1 to resume как исправить ошибку
  • No i o ports were found during enumeration ошибка
  • No host is compatible with the virtual machine ошибка
  • No healthy upstream ошибка что значит
  • No healthy upstream ошибка как исправить