#!/usr/bin/perl =head1 NAME gearmand - Gearman client/worker connector. =head1 SYNOPSIS gearmand --daemon =head1 DESCRIPTION This is the main executable for L. It provides command-line configuration of port numbers, pidfiles, and daemonization. =head1 OPTIONS =over =item --daemonize / -d Make the daemon run in the background (good for init.d scripts, bad for running under daemontools/supervise). =item --port=7003 / -p 7003 Set the port number, defaults to 7003. =item --pidfile=/some/dir/gearmand.pid Write a pidfile when starting up =item --debug=1 Enable debugging (currently the only debug output is when a client or worker connects). =back =head1 COPYRIGHT Copyright 2005-2007, Danga Interactive You are granted a license to use it under the same terms as Perl itself. =head1 WARRANTY This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. =head1 AUTHORS Brad Fitzpatrick Brad Whitaker =head1 SEE ALSO L L L L =cut package Gearmand; use strict; use warnings; BEGIN { $^P = 0x200; # Provide informative names to anonymous subroutines } use FindBin; use lib "$FindBin::Bin/lib"; use Gearman::Server; use Getopt::Long; use Carp; use Danga::Socket 1.52; use IO::Socket::INET; use POSIX (); use Gearman::Util; use vars qw($DEBUG); use Scalar::Util (); $DEBUG = 0; my ( $daemonize, $nokeepalive, $notify_pid, $opt_pidfile, ); my $conf_port = 7003; Getopt::Long::GetOptions( 'd|daemonize' => \$daemonize, 'p|port=i' => \$conf_port, 'debug=i' => \$DEBUG, 'pidfile=s' => \$opt_pidfile, 'notifypid|n=i' => \$notify_pid, # for test suite only. ); daemonize() if $daemonize; # true if we've closed listening socket, and we're waiting for a # convenient place to kill the process our $graceful_shutdown = 0; $SIG{'PIPE'} = "IGNORE"; # handled manually my $server = Gearman::Server->new; my $ssock = $server->create_listening_sock($conf_port); if ($opt_pidfile) { open my $fh, '>', $opt_pidfile or die "Could not open $opt_pidfile: $!"; print $fh "$$\n"; close $fh; } sub shutdown_graceful { return if $graceful_shutdown; my $ofds = Danga::Socket->OtherFds; delete $ofds->{fileno($ssock)}; $ssock->close; $graceful_shutdown = 1; shutdown_if_calm(); } sub shutdown_if_calm { exit 0 unless $server->jobs_outstanding; } sub daemonize { my ($pid, $sess_id, $i); ## Fork and exit parent if ($pid = fork) { exit 0; } ## Detach ourselves from the terminal croak "Cannot detach from controlling terminal" unless $sess_id = POSIX::setsid(); ## Prevent possibility of acquiring a controling terminal $SIG{'HUP'} = 'IGNORE'; if ($pid = fork) { exit 0; } ## Change working directory chdir "/"; ## Clear file creation mask umask 0; ## Close open file descriptors close(STDIN); close(STDOUT); close(STDERR); ## Reopen stderr, stdout, stdin to /dev/null open(STDIN, "+>/dev/null"); open(STDOUT, "+>&STDIN"); open(STDERR, "+>&STDIN"); } kill 'USR1', $notify_pid if $notify_pid; Danga::Socket->EventLoop(); # Local Variables: # mode: perl # c-basic-indent: 4 # indent-tabs-mode: nil # End: