Thread Sauberes starten von lighttpd mit fastcgi (2 answers)
Opened by topeg at 2011-01-21 00:21

topeg
 2011-01-21 00:21
#144897 #144897
User since
2006-07-10
2611 articles
BenutzerIn

user image
Da ich mich mal wieder mit lighttpd und FastCGIs herumgeärgert habe, schrieb ich ein Script, das automatisch nach fastcgi Scripten sucht und diese an lighttpd übergibt (als include_shell)
more (31.3kb):
include_fcgi.pl
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
use File::Spec;
use Getopt::Long qw(:config pass_through);

#map{ print STDERR "$_ => $ENV{$_}\n" }keys(%ENV);
#----------------------------------------------------------------------#
# configuartions

# main config file of lighttpd
# needed to determin "username" "groupname" and "document_root"
my @conf=qw();

# temp dir
my $tmp=File::Spec->tmpdir();

# seach only here for perl scrips
my $bin_path= 'fcgi-bin';

# file suffix
my @suffix = qw();

# max processes of the script allowed
my $max_process=1;

# additional options
my $add='';

my @defult_confs=qw(/etc/lighttpd.conf /etc/lighttpd/lighttpd.conf /usr/lib/lighttpd/lighttpd.conf /usr/local/lib/lighttpd/lighttpd.conf);
#----------------------------------------------------------------------#
# script

GetOptions (
  "config_file=s" => \@conf,
  "suffix=s"      => \@suffix,
  "bin_path=s"    => \$bin_path,
  "max_process=i" => \$max_process,
  "add=s"         =>\$add,
  "tmp=s"         =>\$tmp,
) || exit;

#find a config file if no defined.
# ( CWD is set to conf path )
if(!@conf)
{
  my $first='';
  for(@defult_confs)
  { $first=$_ and last if(-f $_) };

  find(sub{
      if($File::Find::name=~/\.conf$/)
      {
        my $fname=(File::Spec->splitpath())[2];
        if($fname=~/lighttpd\.conf/)
        {
          if($first)
          { unshift(@conf,$File::Find::name); }
          else
          { $first=$File::Find::name; }
        }
        elsif($fname=~/lighttpd\.conf/)
        { unshift(@conf,$File::Find::name); }
        elsif($File::Find::name=~/lighttpd/)
        { push(@conf,$File::Find::name); }
      }
    },File::Spec->rel2abs('.'));

  unshift(@conf,$first) if($first);
}

# read config to find doc-root user and group
my $usr='';
my $grp='';
my $base='';
{
  OUTER:for(@conf)
  {
    open(my $fh, '<', $_) or exit;
    while(my $l=<$fh>)
    {
      $base=$1 if($l=~m!^\s*server.document-root\s*=\s*"([^"]+)"!s);
      $usr=$1  if($l=~m!^\s*server.username\s*=\s*"([^"]+)"!s);
      $grp=$1  if($l=~m!^\s*server.groupname\s*=\s*"([^"]+)"!s);
      last OUTER if($base && $usr && $grp);
    }
    close($fh);
  }
}
exit unless($base && -d $base && $usr && $grp);

# get ids for user and group
my $uid = getpwnam($usr);
my $gid = getgrnam($grp);
exit unless(defined($uid) && defined($gid));

# find files
# files have to be executable by process
my %files=();
find(sub{
    if(!@suffix || grep{$File::Find::name=~/\Q$_\E$/}@suffix)
    {
      my $fname=$File::Find::name;
      my $rname=File::Spec->abs2rel($fname,$base);
      $rname=~s!\\!/!gs;
      $rname="/$rname";
      my ($fperm,$fuid,$fgid)=(stat($fname))[2,4,5];
      $fperm &= 07777;
      if(-f $fname && (($fuid == $uid && $fperm & 00100) || ($fgid == $gid && $fperm & 00010) || $fperm & 00001) )
      { $files{$fname}=$rname; }
    }
  },File::Spec->rel2abs($base,$bin_path));
exit unless(%files);

# load mod_fastcgi
print qq#server.modules += ( "mod_fastcgi" )\n#;

# for each found script create a configuration.
my $cnt=0;
while(my($f,$n)=each(%files))
{
  my $tmp_file=File::Spec->join($tmp,"fastpl.$cnt.socket");
  print <<"EOC";
fastcgi.server += ( "$n" =>
  ((
    "bin-path" => "$f",
    "socket" => "$tmp_file",
    "max_process" => $max_process,
    "bin-copy-environment" => (
      "PATH", "SHELL", "USER"
    ),
    "broken-scriptfilename" => "enable"
$add
  ))
)
EOC
  $cnt++;
}

Aufruf als:
Code: (dl )
include_shell "/usr/local/lib/lighttpd/include_fcgi.pl"


Kommandozeilenargumente:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  --config_file => Pfad zur lighttpd.conf
wenn der wert nicht gesetzt ist versucht das Script eine Konfiguration zu finden

--suffix => Dateiendung für FastCGIs
wenn nichts gesetzt, dann wird jede gefundene ausführbare Datei als FastCGI erkannt.

--bin_path => Suchpfad für FastCGIs
wenn es kein absoluter Pfad ist, dann wird "document_root" als Basispfad genommen

--max_process => Maximale Anzahl der Prozesse die ein CGI-Script parallel haben darf
Default ist 1

--add => Zusätzliche Argumente

--tmp => Verzeichnis in welche die Socket der FastCGIs abgelegt werden
wenn nichts gesetzt nimmt das Scipt den "restbesten" (siehe "tempdir" in File::Spec)


Vorteile:
  • Sucht nach Dateiendung und Pfad
  • Erkennt automatisch ausführbare Dateien
  • Erstellt für jedes Script ein eigenes Socket


Nachteile:
  • nur beim Serverstart/ConfigReload werden die Scripte gefunden
  • Updates von Scripten werden nicht beachtet (Neustart/ConfigReload erforderlich)


EDIT1: Getopt, TempDir Erkennung und automatische ConfigFile Erkennung ergänzt.
EDIT2: Noch ein Suchpfad für die Config ergänzt.
EDIR3: Zeile 133 verbessert (join => rel2abs) dadurch bleiben absolute Pfade in "bin_path" erhalten. Kommandozeilendokumentation.
Last edited: 2011-01-21 03:55:41 +0100 (CET)

View full thread Sauberes starten von lighttpd mit fastcgi