fork & Co.
Andreas Flückiger
- perl
Hallo!
Ich habe Probleme mit fork und setsid. Das Beispiel-Script von Erik Tews (http://www.teamone.de/selfhtml/sfarchiv/1999_2/t03884.htm#a18773) läuft bei mir über Telnet ohne Probleme. Wenn ich es aber über CGI aufrufe, trennt sich das Script nicht ab. Die Meldung, dass das Programm gestartet wurde erscheint erst nach 2 Minuten.
Wisst ihr, was ich dagegen machen könnte, oder gibt es Alternativen?
Vielen Dank im Voraus.
Gruss Andreas
Hallo!
Ich habe Probleme mit fork und setsid. Das Beispiel-Script von Erik Tews (<../../sfarchiv/1999_2/t03884.htm#a18773>) läuft bei mir über Telnet ohne Probleme. Wenn ich es aber über CGI aufrufe, trennt sich das Script nicht ab. Die Meldung, dass das Programm gestartet wurde erscheint erst nach 2 Minuten.
Wisst ihr, was ich dagegen machen könnte, oder gibt es Alternativen?
Vielen Dank im Voraus.
Wie sieht dein Code aus, und auf welchem Unix läuft das Script?
Wie sieht dein Code aus, und auf welchem Unix läuft das Script?
Ich bekomme diese beiden Zeilen beim Telnet-Login. Ich hoffe, dass dies das Richtige ist.
Cobalt Linux release 4.0 (Fargo)
Kernel 2.0.34 on a mips
Den Code übernahm ich 1:1 von deinem Beispielscript, also:
#!/usr/bin/perl
use POSIX qw(setsid);
if (!defined($Pid = fork()))
{
die "Fork konnte nicht ausgeführt werden. Vielleicht unterstützt ihr Betriebssystem diesen Aufruf nicht.";
}
elsif ($Pid == 0)
{
setsid();
sleep (120);
open (TESTDATEI, ">still");
print TESTDATEI "Test\n";
close(TESTDATEI);
close (TESTDATEI);
exit(0);
}
else
{
print "Content-type: text/html\n\n";
print "Ok, das Programm läuft jetzt.";
exit (0);
}
Hm, verstehe ich nicht. Sollte eigendlich gehen. Versuch doch mal folgendes Beispiel von der manpage perlipc auszuführen:
Complete Dissociation of Child from Parent
In some cases (starting server processes, for instance)
you'll want to completely dissociate the child process
from the parent. This is often called daemonization. A
well behaved daemon will also chdir() to the root
directory (so it doesn't prevent unmounting the filesystem
containing the directory from which it was launched) and
redirect its standard file descriptors from and to
/dev/null (so that random output doesn't wind up on the
user's terminal).
use POSIX 'setsid';
sub daemonize {
chdir '/' or die "Can't chdir to /: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>/dev/null'
or die "Can't write to /dev/null: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
}
The fork() has to come before the setsid() to ensure that
you aren't a process group leader (the setsid() will fail
if you are). If your system doesn't have the setsid()
function, open /dev/tty and use the TIOCNOTTY ioctl() on
it instead. See the tty(4) manpage for details.
Non-Unix users should check their Your_OS::Process module
for other solutions.
Wenn das auch nicht geht, liegt es an der dortigen Serverinstallation.
Hm, verstehe ich nicht. Sollte eigendlich gehen. Versuch doch mal folgendes Beispiel von der manpage perlipc auszuführen:
...
Fork und setsid starten zwar einen neuen Prozess (auch bei deinem Script), aber das Hauptprogramm wird erst nach dem neuem Prozess beendet. Das ist auch nicht weiter schlimm, wenn ich verhindern könnte, dass die Ausgabe nicht mehr an den Browser gesendet wird. Leider gelingt mir auch das nicht. Auch die Zeile
open STDOUT, '>/dev/null';
hilft nichts. Konkret möchte ich die Ausgabe (Password: ) folgender Zeilen verhindern:
open(SU,"su $username");
print SU $password;
close(SU);
Kennst du (ihr) eine Lösung?
Gruss
Andreas
Fork und setsid starten zwar einen neuen Prozess (auch bei deinem Script), aber das Hauptprogramm wird erst nach dem neuem Prozess beendet. Das ist auch nicht weiter schlimm, wenn ich verhindern könnte, dass die Ausgabe nicht mehr an den Browser gesendet wird. Leider gelingt mir auch das nicht. Auch die Zeile
open STDOUT, '>/dev/null';
hilft nichts. Konkret möchte ich die Ausgabe (Password: ) folgender Zeilen verhindern:open(SU,"su $username");
print SU $password;
close(SU);Kennst du (ihr) eine Lösung?
Also irgendwas geht da bei dir ganz gewaltig schief. Aber versuch doch mal folgende Zeilen:
open (SU, "su $username > /dev/null");
Dann sollte jede Ausgabe unterdrückt werden. Oder dann gibt es noch so ne Funktion namens IPC::open2, oder so was ähnliches.
Also irgendwas geht da bei dir ganz gewaltig schief. Aber versuch doch mal folgende Zeilen:
open (SU, "su $username > /dev/null");
Dann sollte jede Ausgabe unterdrückt werden. Oder dann gibt es noch so ne Funktion namens IPC::open2, oder so was ähnliches.
Funktioniert leider beides nicht. Merkwürdig finde ich auch die Ausgabe des folgenden Scriptes:
print STDOUT "<!--";
sleep 10;
open(SU,"su $username");
print SU $password;
close(SU);
print STDOUT "-->";
Ausgabe: Password: <!---->
Hi!
Funktioniert leider beides nicht. Merkwürdig finde ich auch die Ausgabe des folgenden Scriptes:
Ausgabe: Password: <!---->
Dies liegt vermutlich daran, dass die Ausgabe noch in den Perl-Puffern haengt. Normalerweise wird erst nach einem \n dieser Puffer geleert (flushed). (Naeheres in perlvar bei $.) Wenn Du keines schreiben willst, koennte folgendes helfen:
$ = 1;
print STDOUT "<!--";
sleep 10;
open(SU,"su $username");
print SU $password;
close(SU);
print STDOUT "-->";
$ = 0;
Bye, Calocybe