No input file specified nginx php windows

I am trying to set a config for Nginx and am facing some issues. In my sites-available there is default file which contains the below code: server { server_name www.test.com test.com; acces...

Resolving «No input file specified» error

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.

source(Resolving «No input file specified» error)

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.

If you are using an NGINX stack on a local machine for development, there might be a preconfigured setting that is playing Gotcha:

open_basedir = "c:/webserver.;c:/”

Here is where I discovered the error on Windows with WinNMP:

Today I wanted to try out Nginx server my windows machine. After setting up the basic server block details for my project, I called the site URL. In the WT-NMP stack to quickly setup the software I needed. In the server block, I needed to specify my root path in a different location other than WWW.

Then when I hit the URL, I was getting “No Input File Specified” for my PHP script.

Now I’m not much of a reader so I just goggled here and there and didn’t found much of a fix. So then I reviewed the php log files. There I got the error message as my project folder path is not within the allowed path(s): (c:/wt-nmp)

So basically I had to edit php.init open_basedir value to include the path I stored my project. However here I could see that even the driver is considered to be as a path. So I ended up placing the driver letter since if I want to store more websites in my ‘d’ drive, I would not encounter this error. This is the final line. I have bold my text to indicate the change I made.

open_basedir = “c:/wt-nmp.;d:/”

“Happy Nginx, is a good Nginx.”

“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.

I’m running php-cgi and NGINX. They are running in a folder, however their root directory is 2 directories out, and 2 in from there. When the root was html (default), they worked perfectly, however now php reports the «No Input File Specified» error. I’ve tried setting the directory to give full control to all programs, I already have full control, I’ve tried to see if php is looking in a different directory, tried changing the directories, hard coding the php variable, etc. I’ve followed about 5 different tutorials on how to fix this problem, but none have resolved it. There are no errors in the console and my fastcgi.conf is unchanged. php and NGINX are both definitely running and communicating, however php fails to get the file for some reason. When accessing any non-php file, NGINX successfully retrieves the file and my browser displays it. I have verified, using netstat, that the only thing listening on port 9100 is my php-cgi. And the only thing listening on port 8080 is NGINX. Both php and NGINX are configured to communicate correctly, and php-cgi is running via RunHiddenConsole.exe which is in the php directory.

Here is the directory tree, in a format similar to YAML:

EclipsePHP
    - Code
        - Blog
            - Source (NGINX/php root Location/Website Source Files)
    - NGINX
        - 1.9.11 (NGINX Executable Location)
            - php (php Executable Location)

And my nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    client_max_body_size 5G;
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        root   ../../Code/Blog/Source;
        client_max_body_size 5G;
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            index  index.php;
            try_files $uri $uri.html $uri/ @extensionless-php;
            index index.html index.htm index.php;
            client_max_body_size 5G;
        }

        error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #

        recursive_error_pages off;

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ .php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ .php$ {
            client_max_body_size 5G;
            try_files      $uri =404;
            include        fastcgi.conf;
            include        fastcgi_params;
            fastcgi_pass   127.0.0.1:9100;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /.ht {
        #    deny  all;
        #}

        location @extensionless-php {
             rewrite ^(.*)$ $1.php last;
        }
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

What could be the cause of this error and how can I resolve it so that I can view the php files properly in my browser? (I am using Eclipse PHP to edit the source, and the error occurs with and without Eclipse running.)

I inherited this web server with Nginx and I’m trying to get a new basic PHP site setup on here.

I’ve followed instructions here.
https://gist.github.com/GhazanfarMir/03bd1f1f770a3834d47274586d46ea62

I can read html files just file in my directory. But for PHP files, I see this error in the webpage:

No input file specified.

Not sure how to resolve this. In my conf file I have this configuration for the PHP and root section:

location / {
    root      /var/www/mydomain.org/html;
    index     index.html index.htm index.php;
    try_files $uri/index.html $uri.html $uri @app;
}

location ~ .php$ {
    fastcgi_split_path_info ^(.+.php)(/.+)$;
    include /etc/nginx/fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME $request_filename;
}

Richard Smith's user avatar

asked Feb 11, 2019 at 22:13

bb2j3z's user avatar

3

The error message «No input file specified» is almost always because the value of SCRIPT_FILENAME does not point to a file. The location ~ .php$ needs to know the document root, and the variable $request_filename is constructed by concatenating the document root with the current URI.

You have defined a document root for the location / block, but not the location ~ .php$ block. Usually, these are the same value, so a single root statement can be placed in the surrounding block, and inherited by all the location blocks that do not override the value.

For example:

root      /var/www/example.org/html;

location / {
    index     index.html index.htm index.php;
    try_files $uri/index.html $uri.html $uri @app;
}

location ~ .php$ {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME $request_filename;
}

location @app {
    ...
}

See this document for details.

answered Feb 12, 2019 at 16:18

Richard Smith's user avatar

Richard SmithRichard Smith

5291 gold badge3 silver badges8 bronze badges

4

I had the same problem.

Check the nginx error.log if you can find a clue as to what it might be.

As I use Windows 11, the problem was the in the «root» folder path which caused a GetFileAttributesEx() error.

The solution was to replace it with /.

Maybe your problem is the root folder path, try using another one.

The path uses RegExp, try: /var/www/example.org/html

answered Sep 19, 2022 at 15:38

Ezequiel Moraes's user avatar

0

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 i o ports were found during enumeration windows 10
  • No hard disk detected при загрузке windows 10
  • No grldr при загрузке windows 10
  • No drivers found при загрузке windows 10
  • No dpk в биосе что это windows