You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Dirk Lutzebaeck <lu...@aeccom.com> on 2003/08/11 23:16:48 UTC

How to restart the root server from within modperl?

Hi,

how can I restart the root httpd server from within modperl? My
problem is that when I call system() with say apachectl restart the
father process is stopped killing the children including the apachectl
itself. So it can't start of again. Can I call something like a reload
of httpd.conf?

Why I want to do this? I have a set of configurations and file links
for different versions for my modperl application which I want to activate
from the modperl application itself (having a HTML user interface).

Thanks for help,

Dirk

Re: How to restart the root server from within modperl?

Posted by Dirk Lutzebaeck <lu...@aeccom.com>.
Thanks, I made it a bit more simple:

  use POSIX;

  if (! fork) { # child
     setsid;
     POSIX::close(0);
     POSIX::close(1);
     exec("restart-apache-command");
  }

Works great!

Thanks,

Dirk




Torsten Foertsch writes:
 > -----BEGIN PGP SIGNED MESSAGE-----
 > Hash: SHA1
 > 
 > On Tuesday 12 August 2003 11:50, Dirk Lutzebaeck wrote:
 > > Dennis Stout writes:
 > >  > On a whim, I would try writing a second script to do the actual shutdown
 > >  > and restart of Apache.
 > >  >
 > >  > Then have your mod_perl program either run it in the background (with a
 > >  > &) or fork it into another process.
 > >
 > > Did exactly that but is has the effect that when the parent (root)
 > > apache is killed it kills all children including the script itself. So
 > > the server wont start again.
 > 
 > I have done something like this several times. My code (it works since 1998 on 
 > a highly used WEB Server with perl5.005_3) looks like that:
 > 
 > ...
 > 
 > sub sysclose {
 >   require 'syscall.ph';
 >   syscall &SYS_close, shift()+0;
 > }
 > 
 > sub RLIMIT_NOFILE {7;}		# this is for LINUX
 > sub getrlimit {
 >   require 'syscall.ph';
 >   my $x="x"x8;			# result
 >   syscall &SYS_getrlimit, shift()+0, $x;
 >   unpack "ii", $x;
 > }
 > 
 > sub close_fd {
 >   my @l=getrlimit( RLIMIT_NOFILE );
 >   my $l;
 > 
 >   for( $l=0; $l<$l[0]; $l++ ) {
 >     next if( $l==2 );		# close all file descriptors except of STDERR
 >     sysclose $l;
 >   }
 > }
 > 
 > sub disconnect_from_apache {
 >   use POSIX qw/setsid/;
 > 
 >   setsid;
 >   close_fd;
 > }
 > 
 > ...
 > 
 >     my $child=fork;
 >     unless( defined $child ) {
 >       ...
 >       return OK;
 >     }
 >     if( $child ) {
 >       my $child_status=0;
 >       if( waitpid( $child, 0 )==$child ) {
 > 	$child_status=$?;
 >       }
 > 
 >       if( $child_status==0 ) {
 >         ...
 > 	return OK;
 >       } else {
 > 	# The first fork succeeded but the second failed
 >         ...
 > 	return OK;
 >       }
 >     } else {
 >       # Child process: fork again to detach from parent process
 >       $child=fork;
 >       CORE::exit( 0 ) if( $child ); # parent exits
 >       unless( defined $child ) {
 >         ...
 > 	CORE::exit( 1 );
 >       }
 >       # Now we are the 2nd child process.
 >       $self->disconnect_from_apache;
 >       $self->doit( ... );                   # <== here comes the real code
 >       CORE::exit( 0 );
 >     }
 > 
 > ...
 > 
 > $self->doit() is called in a separate process group and is not killed by a 
 > signal sent to the apache process group. Further, all files save STDERR are 
 > closed. This is needed since the code runs under mod_perl and the long 
 > running child process inherits the open connection to the browser. If this 
 > connection is not closed the browser shows an endless spinning globe or 
 > something like that in the upper right corner.
 > 
 > Torsten
 > -----BEGIN PGP SIGNATURE-----
 > Version: GnuPG v1.0.7 (GNU/Linux)
 > 
 > iD8DBQE/OSIAwicyCTir8T4RAv3RAKCXdpbHLQepeOZFCyXt1KkMVGnwPgCeNu7X
 > hlC1NSEv0NsA7LlM7lol7wI=
 > =xId6
 > -----END PGP SIGNATURE-----
 > 

Re: How to restart the root server from within modperl?

Posted by Torsten Foertsch <to...@gmx.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tuesday 12 August 2003 11:50, Dirk Lutzebaeck wrote:
> Dennis Stout writes:
>  > On a whim, I would try writing a second script to do the actual shutdown
>  > and restart of Apache.
>  >
>  > Then have your mod_perl program either run it in the background (with a
>  > &) or fork it into another process.
>
> Did exactly that but is has the effect that when the parent (root)
> apache is killed it kills all children including the script itself. So
> the server wont start again.

I have done something like this several times. My code (it works since 1998 on 
a highly used WEB Server with perl5.005_3) looks like that:

...

sub sysclose {
  require 'syscall.ph';
  syscall &SYS_close, shift()+0;
}

sub RLIMIT_NOFILE {7;}		# this is for LINUX
sub getrlimit {
  require 'syscall.ph';
  my $x="x"x8;			# result
  syscall &SYS_getrlimit, shift()+0, $x;
  unpack "ii", $x;
}

sub close_fd {
  my @l=getrlimit( RLIMIT_NOFILE );
  my $l;

  for( $l=0; $l<$l[0]; $l++ ) {
    next if( $l==2 );		# close all file descriptors except of STDERR
    sysclose $l;
  }
}

sub disconnect_from_apache {
  use POSIX qw/setsid/;

  setsid;
  close_fd;
}

...

    my $child=fork;
    unless( defined $child ) {
      ...
      return OK;
    }
    if( $child ) {
      my $child_status=0;
      if( waitpid( $child, 0 )==$child ) {
	$child_status=$?;
      }

      if( $child_status==0 ) {
        ...
	return OK;
      } else {
	# The first fork succeeded but the second failed
        ...
	return OK;
      }
    } else {
      # Child process: fork again to detach from parent process
      $child=fork;
      CORE::exit( 0 ) if( $child ); # parent exits
      unless( defined $child ) {
        ...
	CORE::exit( 1 );
      }
      # Now we are the 2nd child process.
      $self->disconnect_from_apache;
      $self->doit( ... );                   # <== here comes the real code
      CORE::exit( 0 );
    }

...

$self->doit() is called in a separate process group and is not killed by a 
signal sent to the apache process group. Further, all files save STDERR are 
closed. This is needed since the code runs under mod_perl and the long 
running child process inherits the open connection to the browser. If this 
connection is not closed the browser shows an endless spinning globe or 
something like that in the upper right corner.

Torsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)

iD8DBQE/OSIAwicyCTir8T4RAv3RAKCXdpbHLQepeOZFCyXt1KkMVGnwPgCeNu7X
hlC1NSEv0NsA7LlM7lol7wI=
=xId6
-----END PGP SIGNATURE-----

Re[2]: How to restart the root server from within modperl?

Posted by "Mike P. Mikhailov" <mi...@sibtel.ru>.
Hello Dirk Lutzebaeck,

Tuesday, August 12, 2003, 3:50:01 PM, you wrote:


DL> Dennis Stout writes:
DL>  > On a whim, I would try writing a second script to do the actual shutdown and
DL>  > restart of Apache.
DL>  > 
DL>  > Then have your mod_perl program either run it in the background (with a &) or
DL>  > fork it into another process.

DL> Did exactly that but is has the effect that when the parent (root)
DL> apache is killed it kills all children including the script itself. So
DL> the server wont start again.

DL> Dirk

Try double fork. I'm used this approach to start long running job.
Job must be done even apache process die. So they completly detached
from parent apache process.

Read this, I hope this relevant

http://perl.apache.org/docs/1.0/guide/performance.html#Avoiding_Zombie_Processes

-- 
WBR, Mike P. Mikhailov

mailto: mike@sibtel.ru
ICQ:    280990142

If you put three drops of poison into a 100 percent pure Java, you get - Windows.
If you put a few drops of Java into Windows, you still have Windows.


Re: How to restart the root server from within modperl?

Posted by Frank Maas <fr...@cheiron-it.nl>.
On Tue, Aug 12, 2003 at 11:50:01AM +0200, Dirk Lutzebaeck wrote:
> 
> Dennis Stout writes:
>  > On a whim, I would try writing a second script to do the actual shutdown and
>  > restart of Apache.
>  > 
>  > Then have your mod_perl program either run it in the background (with a &) or
>  > fork it into another process.
> 
> Did exactly that but is has the effect that when the parent (root)
> apache is killed it kills all children including the script itself. So
> the server wont start again.

Since you are talking about a management tool via http, you might consider
using a second server process for this. If you select the 'restart link'
then under water you need to (a) startup a server on a different port,
(b) redirect to a URI on that server, (c) make it that that URI restarts
the main server as you would normally do, (d) clean up the second server
as soon as the main server restarts.
You can do this in a sophisticated manner by creating a httpd config on
the fly, using a unique restart-URI, thus avoiding the most obvious 
security risks.

Might work...

--Frank

Re: How to restart the root server from within modperl?

Posted by Dirk Lutzebaeck <lu...@aeccom.com>.
Dennis Stout writes:
 > On a whim, I would try writing a second script to do the actual shutdown and
 > restart of Apache.
 > 
 > Then have your mod_perl program either run it in the background (with a &) or
 > fork it into another process.

Did exactly that but is has the effect that when the parent (root)
apache is killed it kills all children including the script itself. So
the server wont start again.

Dirk

Re: How to restart the root server from within modperl?

Posted by Dirk Lutzebaeck <lu...@aeccom.com>.
Martin Langhoff writes:
 >  >>how can I restart the root httpd server from within modperl?
 > 
 > Use `at` to schedule it a minute in the future -- effectively forking it.

Yes, also thought of that but the smallest unit of 'at' is minutes and
I want to restart the server immediately.

 > Note that normally apache starts as root and runs as an unprivileged 
 > user. If this is the case you _can_ achieve it using a suid wrapper or 
 > sudo, but you'll risk opening a very serious security hole in the 
 > system. So don't. Instead, run apache as a regular user, on a high port.

I used sudo.

Dirk

[Slightly OT] Port forwarding (Was: How to restart the root server from within modperl?)

Posted by Andrew Ho <an...@tellme.com>.
Hello,

ML>If you absolutely need to be in port 80, either setup a simple 
ML>lightweight apache on port 80 as a reverse proxy (see the mod_perl 
ML>guide) or, even simpler, do some port forwarding from port 80 to your 
ML>high port of choice.

Has anybody had very good experiences using a simple port forwarder in a
production setup? We had a somewhat bad experience with using portfwd
under Solaris (images and other binary data got randomly corrupted, and we
never got around to figuring out why), and I'm wondering what others use
instead. It seems like the port forwarder involved would also be important
performance wise.

The applications I am typically interested in are forwarding ports on the
same interface (like the port 80 example here) as well as between
interfaces (or between external interfaces and loopback).

Humbly,

Andrew

----------------------------------------------------------------------
Andrew Ho               http://www.tellme.com/       andrew@tellme.com
Engineer                    1-800-555-TELL          Voice 650-930-9062
Tellme Networks, Inc.                                 Fax 650-930-9101
----------------------------------------------------------------------


Re: How to restart the root server from within modperl?

Posted by Martin Langhoff <ml...@nzl.com.ar>.
 >>how can I restart the root httpd server from within modperl?

Use `at` to schedule it a minute in the future -- effectively forking it.

Note that normally apache starts as root and runs as an unprivileged 
user. If this is the case you _can_ achieve it using a suid wrapper or 
sudo, but you'll risk opening a very serious security hole in the 
system. So don't. Instead, run apache as a regular user, on a high port.

If you absolutely need to be in port 80, either setup a simple 
lightweight apache on port 80 as a reverse proxy (see the mod_perl 
guide) or, even simpler, do some port forwarding from port 80 to your 
high port of choice.

regards,



martin



Re: How to restart the root server from within modperl?

Posted by Dennis Stout <st...@stout.dyndns.org>.
On a whim, I would try writing a second script to do the actual shutdown and
restart of Apache.

Then have your mod_perl program either run it in the background (with a &) or
fork it into another process.

Just a thought.

Dennis

S.T.O.U.T. = Synthetic Technician Optimized for Ultimate Troublshooting
----- Original Message ----- 
From: "Dirk Lutzebaeck" <lu...@aeccom.com>
To: <mo...@perl.apache.org>
Sent: Monday, August 11, 2003 13 16
Subject: How to restart the root server from within modperl?


>
> Hi,
>
> how can I restart the root httpd server from within modperl? My
> problem is that when I call system() with say apachectl restart the
> father process is stopped killing the children including the apachectl
> itself. So it can't start of again. Can I call something like a reload
> of httpd.conf?
>
> Why I want to do this? I have a set of configurations and file links
> for different versions for my modperl application which I want to activate
> from the modperl application itself (having a HTML user interface).
>
> Thanks for help,
>
> Dirk


RE: How to restart the root server from within modperl?

Posted by Egor Shipovalov <mo...@eonline.ru>.
Why not start the Apache from a shell script that would always start it
again if it dies?
To restart the Apache then, you'd just kill the root httpd with apachectl.
Killing the paernt shell script would terminate the whole operation.

Egor.

> -----Original Message-----
> From: Dirk Lutzebaeck [mailto:lutzeb@aeccom.com]
> Sent: Tuesday, August 12, 2003 1:17
> To: modperl@perl.apache.org
> Subject: How to restart the root server from within modperl?
>
>
>
> Hi,
>
> how can I restart the root httpd server from within modperl? My
> problem is that when I call system() with say apachectl restart the
> father process is stopped killing the children including the apachectl
> itself. So it can't start of again. Can I call something like a reload
> of httpd.conf?
>
> Why I want to do this? I have a set of configurations and file links
> for different versions for my modperl application which I want to activate
> from the modperl application itself (having a HTML user interface).
>
> Thanks for help,
>
> Dirk


RE: How to restart the root server from within modperl?

Posted by Egor Shipovalov <mo...@eonline.ru>.
> Can I call something like a reload of httpd.conf?

This is what sending a SIGHUP to Apache does. However, both mod_perl-enabled
servers I run misbehave on this, so I always do a full restart.

Egor.