Set Variable from Content of Text File?

Hello Nginx Community, and Happy New Year…

Is it possible to set the value of a variable based on the contents of a
text file?

So if there is site downtime, I can place a file in a directory that
nginx will see and will know to serve a downtime notice, but then can
nginx read the contents of the file to determine which downtime notice
to serve?

Thanks,

John

John,

See Ezra’s response in the thread here:
http://thread.gmane.org/gmane.comp.web.nginx.english/8978/focus=8990

That explanation is just for a single downtime notice, but you can use a
variation of his solution to accomplish what you want. For example:

server {

if (-f $document_root/system/back_soon.html) {
rewrite ^(.)$ /system/back_soon.html last;
break;
}
if (-f $document_root/system/down_for_a_while.html) {
rewrite ^(.
)$ /system/down_for_a_while.html last;
break;
}

}

This will show the back_soon.html page if it exists. If it doesn’t
exist
and the down_for_a_while.html page does, then that will be displayed.
Otherwise, processing will continue normally.

Hi Nick,

Thanks for your response… I understand the response below, but I was
hoping for a way of doing this by reading the contents of the text
file… So something like this…

if (-f $document_root/system/back_soon.txt) {

        set $file_to_load read /$document_root/system/back_soon.txt
        rewrite  ^(.*)$  $file_to_load last;
        break;

}

So if the file exists read and set a variable based on the contents of
the file, and then rewrite to the variable path.

Thanks,

John

Hi John,

That’s an interesting problem. There’s no way that I’ve seen that would
let
you read the contents of a file from the nginx config. Maybe someone
else
can shed some light on this.

In any case, I’m not sure you’d want the overhead of opening and reading
a
file on every request. However, you might be able to come up with a
solution using symlinks and/or a simple cron script that will make the
appropriate file available to nginx when necessary. A command like this
might work…

if [ -s maintenance_file.txt ]; then ln -s cat maintenance_file.txt
maintenance.html; elif [ -f maintenance.html ]; then rm
maintenance.html; fi

I tested this out locally, and it works. If the maintenance_file.txt
file
has text in it, it assumes the text is a filename and creates a symlink
to
that filename (at a location where nginx would see the symlink and serve
the
linked file as a maintenance page). If the maintenance_file.txt is
empty
and the symlink exists, then the symlink is deleted. (This could be
made
much more robust, but it works as is if the maintenance_file.txt is
either
empty or contains a single line with no newline/return characters.)

I realize this isn’t exactly what you’re going for, but it might
accomplish
your goal. And ultimately, this will be more performant than having
nginx
read the contents of a file on each request.

Nick

Hi Nick,

Thanks for your thoughts, I really appreciate it!

I know nginx is all about speed, and reading a file each time can be a
waste of resources (hence no htaccess). I’m not skilled in module
development, but do you think it would be possible either as a custom
module, or using the embedded perl module to accomplish this?

There are a few things that I want to do besides the maintenance page,
and basically they require the ability of setting a variable to the
contents of a text file, which allows nginx to make some decisions,
instead of checking for the existence of lots of files. Lets say I have
10 things I want nginx to do… wouldn’t checking for the existence of
10 different files have more overhead than just reading the contents of
one?

http://wiki.codemongers.com/NginxHttpAccessKeyModule

For example the access key module. Right now the access key signature is
defined in the config file, and supports variables. So instead of
changing the config file to change the signature, I could set the
signature to a variable, and have that variable read each time from a
text file, that could change anytime I wanted (and be different for
different directories), without having to edit the config file and
reload from command line.

Thanks,

John

On Thu, Jan 08, 2009 at 09:20:49PM -0600, Nick P. wrote:

if (-f $document_root/system/back_soon.html) {

This will show the back_soon.html page if it exists. If it doesn’t exist
and the down_for_a_while.html page does, then that will be displayed.
Otherwise, processing will continue normally.

With modern try_files directive this can be done as

  location / {
       try_files  /system/back_soon.html
                  /system/down_for_a_while.html
                  ;

       openfile_cache  max=10000;
       open_file_cache_valid    30s;
       open_file_cache_errors   on;
  }

Hi John,

I’ve not done any module development myself, so I don’t know the
specific
capabilities, but I don’t see why this wouldn’t be possible to
accomplish.
Perhaps a module that does exactly as you say and sets a variable using
the
contents of a file, or a module that could read the contents of a file
containing one or more variable declarations. It would be good to be
able
to specify when the file should be reloaded. This could be set to a
number
of requests between reloads, amount of time between reloads, or reloads
based on some condition of a request.

Although I’ve not come across this need myself yet, I can see where it
could
be quite useful.

Nick