3

Is it possible to set timeout directives within a location block to prevent nginx returning a 504 from a long running PHP script (PHP-FPM)?

server
{
  listen 80;
  server_name ubuntu-vm.test-api;
  root /home/me/Sites/path/to/site/; 
  index index.php;

  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ \.php$ {


    try_files $uri =404;

    # Fix for server variables that behave differently under nginx/php-fpm than typically expected
    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    # Include the standard fastcgi_params file included with nginx
    include fastcgi_params;
    fastcgi_param  PATH_INFO        $fastcgi_path_info;
    fastcgi_index index.php;

    # Override the SCRIPT_FILENAME variable set by fastcgi_params
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

    # Pass to upstream PHP-FPM; This must match whatever you name your upstream connection
    fastcgi_pass unix:/var/run/php5-fpm.sock;

    }

    location /someurlpath {

    try_files $uri $uri/ /index.php?$query_string;

    # Fix for server variables that behave differently under nginx/php-fpm than typically expected
    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    # Include the standard fastcgi_params file included with nginx
    include fastcgi_params;
    fastcgi_param  PATH_INFO        $fastcgi_path_info;
    fastcgi_index index.php;

    # Override the SCRIPT_FILENAME variable set by fastcgi_params
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

    # Pass to upstream PHP-FPM; This must match whatever you name your upstream connection
    fastcgi_pass unix:/var/run/php5-fpm.sock;

    fastcgi_read_timeout 100000s;
    }

    error_log /var/log/nginx/my_api_error.log;
    access_log /var/log/nginx/my_api_access.log;
}

This has no effect when making a request to example.com/someurlpath. The timeout occurs after approximately 60 seconds. PHP is configured to allow the script to run until completion (set_time_limit(0))

If I set the fastcgi_read_timeout in the main ~ /.php {} block this resolves the issue.

I don't want to set a global timeout for all scripts.

3
+50

First, take a look at nested locations. The reason why your second location block isn't taken into account is because when nginx matches a location, it stops. So, http://ubuntu-vm.test-api/someurlpath, if theres an index.php in the corresponding folder, only matches the location ~ \.php$ !

I've stumbled upon this interesting blog post

To sum this up, you need to:

  1. Increase the max_execution_time configuration variable in your php.ini.
  2. Increase the request_terminate_timeout configuration variable of php-fpm.
  3. Set the fastcgi_read_timeout in the location you want, in the nginx configuration file.

The trouble is you can't tell php-fpm to use a different configuration file only for that one location.

However, you can set a php.ini configuration variable in your nginx configuration like so:

fastcgi_param PHP_VALUE "max_execution_time=1000";
  • That last part about setting fastcgi_param also won't work to set different execution times for different locations because with PHP-FPM, the fastcgi_param settings you set end up applying to all PHP threads. So that ends up being essentially a global setting. – orrd Aug 2 '16 at 21:21
  • That's interesting, @orrd. Thanks for the precision. I'll be editing my post, but could you link to your source first, please? – moebius_eye Aug 5 '16 at 0:26
  • Good question @moebius_eye! What I said is mentioned in numerous ServerFault answers, but some suggest the opposite. I couldn't find any official documentation on using fastcgi_param to set PHP_VALUE and PHP_FLAG at all. These bug reports are the most official sources I can find: bugs.php.net/bug.php?id=63965 bugs.php.net/bug.php?id=53611. I ran some tests and found that setting a PHP_VALUE in any location block will become a global value for all PHP scripts. However, if you set also different PHP_VALUE for another block, it seems to maybe (consistently??) set each PHP_VALUE for each. – orrd Aug 6 '16 at 0:46
1

I ran into the same problem, and while I think you could use the Nginx configuration to set fastcgi_read_timeout per location as you're trying to do, it ends up being complicated to configure the locations properly that way. And then it may still timeout if you don't also set PHP's max_execution_time.

I found that a better solution is to set it up so that the Nginx timeouts aren't really used, and let PHP handle the timeouts instead (as it does with other servers like mod-Apache and the command line).

So in your Nginx configuration's "location ~ .php$" section, set request_terminate_timeout to a very high value (or better yet, set it to 0 to disable the timeout). And also set fastcgi_read_timeout to the highest number of seconds you could possibly want any script to run.

And then fine-tune it by setting a default value by setting max_execution_time in your php.ini. Now, when you have script that you want to allow to run for a long time, use the set_time_limit() PHP command in those scripts.

0

You can set the timeouts in any location, server or http block, as shown in the nginx documentation. They will be inherited from the containing block, which is why the snippet you posted did not work.

  • What are you talking about? – Michael Hampton Jun 12 '14 at 16:12
  • I tried this and pasted my config. Can you shed any light on this? There is now some bounty attached to the question. Many thanks. – codecowboy Jun 21 '14 at 5:41
0

have you tried to set fastcgi_pass inside that location?

location {
     fastcgi_pass 127.0.0.1:9000;
     fastcgi_read_timeout 100000s;
}
  • I updated my question with the config I tried – codecowboy Jun 17 '14 at 23:26
  • It's insufficient: php-fpm will stop the execution before that timeout. – moebius_eye Jun 24 '14 at 9:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.