Acme-Ghost
view release on metacpan or search on metacpan
lib/Acme/Ghost.pm view on Meta::CPAN
This attribute sets facility for logging
See L<Acme::Ghost::Log/facility>
=head2 group
group => 'nogroup',
group => 65534,
This attribute sets group/gid for spawned process
=head2 ident
ident => 'myDaemon',
This attribute sets ident string for system log (syslog)
=head2 logfile
logfile => '/var/log/myDaemon.log',
lib/Acme/Ghost.pm view on Meta::CPAN
If this status is false, then it is immediately to shut down Your process
as soon as possible, otherwise your process will be forcibly destroyed
within 7 seconds from the moment your process receives the corresponding signal
=head2 pid
print $g->pid;
This method returns PID of the daemon
=head2 set_gid
$g = $g->set_gid('1000 10001 10002');
$g = $g->set_gid(1000);
$g = $g->set_gid('nogroup');
$g = $g->set_gid;
Become another group. Arguments are groups (or group ids or space delimited list of group ids). All errors die
=head2 set_uid
$g = $g->set_uid(1000);
$g = $g->set_uid('nobody');
$g = $g->set_uid;
Become another user. Argument is user (or userid). All errors die
lib/Acme/Ghost.pm view on Meta::CPAN
if (IS_ROOT) {
if ($user =~ /^(\d+)$/) {
$uid = $user;
} elsif (length($user)) {
$uid = getpwnam($user) || croak "getpwnam failed - $!\n";
}
}
$user = getpwuid($uid || 0) unless length $user;
# Get GID by Group
my $gids = $); # Effect. GIDs
if (IS_ROOT) {
if ($group =~ /^(\d+)$/) {
$gids = $group;
} elsif (length($group)) {
$gids = getgrnam($group) || croak "getgrnam failed - $!\n";
}
}
my $gid = (split /\s+/, $gids)[0]; # Get first GID
$group = getpwuid($gid || 0) unless length $group;
# Check name
croak "Can't create unnamed daemon\n" unless $name;
my $self = bless {
name => $name,
user => $user,
group => $group,
uid => $uid,
gid => $gid,
gids => $gids,
# PID
pidfile => $args->{pidfile} || File::Spec->catfile(getcwd(), sprintf("%s.pid", $name)),
_filepid => undef,
# Log
facility => $args->{facility},
logfile => $args->{logfile},
ident => $args->{ident} || $name,
logopt => $args->{logopt},
lib/Acme/Ghost.pm view on Meta::CPAN
POSIX::setuid($uid) || die "Setuid $uid failed - $!\n";
if ($< != $uid || $> != $uid) { # check $> also (rt #21262)
$< = $> = $uid; # try again - needed by some 5.8.0 linux systems (rt #13450)
if ($< != $uid) {
die "Detected strange UID. Couldn't become UID \"$uid\": $!\n";
}
}
return $self;
}
sub set_gid {
my $self = shift;
my $gids = shift // $self->{gids};
return $self unless IS_ROOT; # Skip if no ROOT
return $self unless defined $gids; # Skip if no GIDs
# Get GIDs
my $gid = (split /\s+/, $gids)[0]; # Get first GID
$) = "$gid $gids"; # store all the GIDs (calls setgroups)
POSIX::setgid($gid) || die "Setgid $gid failed - $!\n"; # Set first GID
if (! grep {$gid == $_} split /\s+/, $() { # look for any valid id in the list
die "Detected strange GID. Couldn't become GID \"$gid\": $!\n";
}
return $self;
}
sub daemonize {
my $self = shift;
my $safe = shift;
croak "This process is already daemonized (PID=$$)\n" if $self->{daemonized};
# Check PID
my $pid_file = $self->filepid->file; # PID File
if ( my $runned = $self->filepid->running ) {
die "Already running $runned\n";
}
# Store current PID to instance as Parent PID
$self->{ppid} = $$;
# Get UID & GID
my $uid = $self->{uid}; # UID
my $gids = $self->{gid}; # returns list of groups (gids)
my $gid = (split /[\s,]+/, $gids)[0]; # First GID
_debug("!! UID=%s; GID=%s; GIDs=\"%s\"", $uid, $gid, $gids);
# Pre Init Hook
$self->preinit;
$self->{_log} = undef; # Close log handlers before spawn
# Spawn
my $pid = _fork();
if ($pid) {
_debug("!! Spawned (PID=%s)", $pid);
if ($safe) { # For internal use only
$self->{pid} = $pid; # Store child PID to instance
return $self;
}
exit 0; # exit parent process
}
# Child
$self->{daemonized} = 1; # Set daemonized flag
$self->filepid->pid($$)->save; # Set new PID and Write PID file
chown($uid, $gid, $pid_file) if IS_ROOT && -e $pid_file;
# Set GID and UID
$self->set_gid->set_uid;
# Turn process into session leader, and ensure no controlling terminal
unless (DEBUG) {
die "Can't start a new session: $!" if POSIX::setsid() < 0;
}
# Init logger!
my $log = $self->log;
# Close all standart filehandles
( run in 1.388 second using v1.01-cache-2.11-cpan-ceb78f64989 )