mirror of
				https://github.com/openresty/openresty.git
				synced 2024-10-13 00:29:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			227 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env perl
 | |
| 
 | |
| # Copyright (C) Yichun Zhang (agentzh)
 | |
| 
 | |
| # TODO: port this script into the nginx core for greater flexibility
 | |
| # and better performance.
 | |
| 
 | |
| use strict;
 | |
| use warnings;
 | |
| 
 | |
| use File::Spec ();
 | |
| use FindBin ();
 | |
| use Getopt::Std qw( getopts );
 | |
| use File::Temp qw( tempdir );
 | |
| use POSIX qw( WNOHANG );
 | |
| 
 | |
| my %opts;
 | |
| getopts("he:c:V", \%opts)
 | |
|     or usage(1);
 | |
| 
 | |
| if ($opts{h}) {
 | |
|     usage(0);
 | |
| }
 | |
| 
 | |
| my $nginx_path = File::Spec->catfile($FindBin::Bin, "..", "nginx", "sbin", "nginx");
 | |
| #warn $nginx_path;
 | |
| if (!-f $nginx_path) {
 | |
|     $nginx_path = "nginx";  # find in PATH
 | |
| }
 | |
| 
 | |
| if ($opts{V}) {
 | |
|     exec "$nginx_path -V";
 | |
| }
 | |
| 
 | |
| my $luafile;
 | |
| if (!defined $opts{e}) {
 | |
|     $luafile = shift
 | |
|         or die qq{No Lua input file nor -e "" option specified.\n};
 | |
| }
 | |
| 
 | |
| if (@ARGV) {
 | |
|     die "unknown arguments: @ARGV\n";
 | |
| }
 | |
| 
 | |
| my $conns = $opts{c} || 64;
 | |
| 
 | |
| my @nameservers;
 | |
| 
 | |
| # try to read the nameservers used by the system resolver:
 | |
| if (open my $in, "/etc/resolv.conf") {
 | |
|     while (<$in>) {
 | |
|         if (/^\s*nameserver\s+(\d+(?:\.\d+){3})(?:\s+|$)/) {
 | |
|             push @nameservers, $1;
 | |
|             if (@nameservers > 10) {
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     close $in;
 | |
| }
 | |
| 
 | |
| if (!@nameservers) {
 | |
|     # default to Google's open DNS servers
 | |
|     push @nameservers, "8.8.8.8", "8.8.4.4";
 | |
| }
 | |
| 
 | |
| warn "@nameservers\n";
 | |
| 
 | |
| my $prefix_dir = tempdir(CLEANUP => 1);
 | |
| #warn "prefix dir: $prefix_dir\n";
 | |
| 
 | |
| my $logs_dir = File::Spec->catfile($prefix_dir, "logs");
 | |
| mkdir $logs_dir or die "failed to mkdir $logs_dir: $!";
 | |
| 
 | |
| my $conf_dir = File::Spec->catfile($prefix_dir, "conf");
 | |
| mkdir $conf_dir or die "failed to mkdir $conf_dir: $!";
 | |
| 
 | |
| my $chunk_name;
 | |
| if (defined $opts{e}) {
 | |
|     $luafile = File::Spec->catfile($conf_dir, "a.lua");
 | |
|     open my $out, ">$luafile"
 | |
|         or die "Cannot open $luafile for writing: $!\n";
 | |
|     print $out $opts{e};
 | |
|     close $out;
 | |
|     $chunk_name = "=(command line -e)";
 | |
| 
 | |
| } else {
 | |
|     $chunk_name = "\@$luafile";
 | |
| }
 | |
| 
 | |
| my $loader = <<_EOC_;
 | |
|             local gen
 | |
|             do
 | |
|                 local fname = "$luafile"
 | |
|                 local f = assert(io.open(fname, "r"))
 | |
|                 local chunk = f:read("*a")
 | |
|                 gen = assert(loadstring(chunk, "$chunk_name"))
 | |
|             end
 | |
| _EOC_
 | |
| 
 | |
| my $conf_file = File::Spec->catfile($conf_dir, "nginx.conf");
 | |
| open my $out, ">$conf_file"
 | |
|     or die "Cannot open $conf_file for writing: $!\n";
 | |
| 
 | |
| print $out <<_EOC_;
 | |
| daemon off;
 | |
| master_process off;
 | |
| worker_processes 1;
 | |
| 
 | |
| env LD_LIBRARY_PATH;
 | |
| env LD_PRELOAD;
 | |
| env PATH;
 | |
| env LUA_PATH;
 | |
| env LUA_CPATH;
 | |
| 
 | |
| error_log /dev/stderr warn;
 | |
| #error_log /dev/stderr debug;
 | |
| 
 | |
| events {
 | |
|     worker_connections $conns;
 | |
| }
 | |
| 
 | |
| http {
 | |
|     access_log off;
 | |
|     lua_socket_log_errors off;
 | |
|     resolver @nameservers;
 | |
| 
 | |
|     init_by_lua '
 | |
|         local stdout = io.stdout
 | |
|         print = function (...) stdout:write(...) end
 | |
|         ngx.print = print
 | |
|         ngx.say = function (...) print(...) print("\\\\n") end
 | |
|     ';
 | |
| 
 | |
|     init_worker_by_lua '
 | |
|         local exit = os.exit
 | |
|         local stderr = io.stderr
 | |
| 
 | |
|         local function handle_err(err)
 | |
|             if err then
 | |
|                 err = string.gsub(err, "^init_worker_by_lua:%d+: ", "")
 | |
|                 stderr:write(err)
 | |
|             end
 | |
|             return exit(1)
 | |
|         end
 | |
| 
 | |
|         local ok, err = pcall(function ()
 | |
| $loader
 | |
|             -- print("calling timer.at...")
 | |
|             local ok, err = ngx.timer.at(0, function ()
 | |
|                 -- io.stderr:write("timer firing")
 | |
|                 local ok, err = pcall(gen)
 | |
|                 if not ok then
 | |
|                     return handle_err(err)
 | |
|                 end
 | |
|                 local rc = err
 | |
|                 if rc and type(rc) ~= "number" then
 | |
|                     return handle_err("bad return value of type " .. type(rc))
 | |
|                 end
 | |
|                 return exit(rc)
 | |
|             end)
 | |
|             if not ok then
 | |
|                 return handle_err(err)
 | |
|             end
 | |
|             -- print("timer created")
 | |
|         end)
 | |
| 
 | |
|         if not ok then
 | |
|             return handle_err(err)
 | |
|         end
 | |
|     ';
 | |
| }
 | |
| _EOC_
 | |
| 
 | |
| close $out;
 | |
| 
 | |
| my $cmd = "$nginx_path -p $prefix_dir/";
 | |
| 
 | |
| my $child_pid;
 | |
| 
 | |
| sub sigint {
 | |
|     $SIG{INT} = \&sigint;
 | |
|     if ($child_pid) {
 | |
|         kill INT => $child_pid;
 | |
|     }
 | |
| }
 | |
| $SIG{INT} = \&sigint;
 | |
| 
 | |
| my $pid = fork();
 | |
| 
 | |
| if (!defined $pid) {
 | |
|     die "fork() failed: $!\n";
 | |
| }
 | |
| 
 | |
| if ($pid == 0) {  # child process
 | |
|     #warn "exec $cmd...";
 | |
|     exec $cmd;
 | |
| 
 | |
| } else {
 | |
|     $child_pid = $pid;
 | |
|     waitpid($child_pid, 0);
 | |
|     exit($? || 0);
 | |
| }
 | |
| 
 | |
| sub usage {
 | |
|     my $rc = shift;
 | |
|     my $msg = <<_EOC_;
 | |
| resty [-h] [-c num] [-e prog] [-V] [lua-file]
 | |
| 
 | |
| Options:
 | |
|     -c num      set maximal connection count (default: 64).
 | |
|     -e prog     run the inlined Lua code in "prog".
 | |
|     -h          print this help.
 | |
|     -V          print the underlying nginx version and configurations.
 | |
| 
 | |
| For bug reporting instructions, please see:
 | |
| <http://openresty.org/#Community>
 | |
| _EOC_
 | |
|     if ($rc == 0) {
 | |
|         print $msg;
 | |
|         exit(0);
 | |
|     }
 | |
| 
 | |
|     warn $msg;
 | |
|     exit($rc);
 | |
| }
 |