laravel-signal-aware-command

repository·main·Indexed 41 days ago

https://github.com/spatie/laravel-signal-aware-command

A package that allows Laravel Artisan commands to gracefully handle system signals like SIGINT and SIGTERM. It provides a SignalAwareCommand base class, a Signal facade for registering handlers, and a SignalReceived event for intercepting signals to perform cleanup or logging tasks.

Tokens
2K
Snippets
10
Records
10
Agent score
50%

What's inside laravel-signal-aware-command

  1. How to make an Artisan command signal aware

    main

    To enable signal awareness in an Artisan command, you must change its base class from Illuminate\Console\Command to Spatie\SignalAwareCommand\SignalAwareCommand.

    use Spatie\SignalAwareCommand\SignalAwareCommand;
    
    class YourCommand extends SignalAwareCommand
    {
        // your code
    }
  2. Install the laravel-signal-aware-command package

    main

    Install the package via Composer to enable signal handling (like SIGINT or SIGTERM) in your Laravel Artisan commands.

    composer require spatie/laravel-signal-aware-command
  3. Handle signals directly on the command

    main

    You can handle specific signals by defining a method on your command class following the naming convention on followed by the signal name (e.g., onSigint for SIGINT). This is the simplest way to add signal-specific logic directly to the command class.

    use Spatie\SignalAwareCommand\SignalAwareCommand;
    
    class YourCommand extends SignalAwareCommand
    {
        protected $signature = 'your-command';
    
        public function handle()
        {
            $this->info('Command started...');
            sleep(100);
        }
    
        public function onSigint()
        {
            // will be executed when you stop the command
            $this->info('You stopped the command!');
        }
    }
  4. Handle signals via the Signal facade

    main

    The Signal facade allows you to register signal handlers from anywhere in your application.

    Requirements:

    1. You must define which signals the command is listening for by setting the $handlesSignals property on your command class.
    2. Use Signal::handle(int $signal, Closure $callback) to register the logic. The callback receives the command instance that received the signal as its first argument.

    Clearing Handlers:

    • Signal::clearHandlers(int $signal): Removes handlers for a specific signal.
    • Signal::clearHandlers(): Removes all handlers for all signals.
    use Illuminate\Console\Command;
    use Spatie\SignalAwareCommand\Facades\Signal;
    
    // 1. Define signals in the command
    class YourCommand extends SignalAwareCommand
    {
        protected $signature = 'your-command';
        protected $handlesSignals = [SIGINT];
    
        public function handle()
        {
            (new SomeOtherClass())->performSomeWork();
            sleep(100);
        }
    }
    
    // 2. Register handler anywhere else
    class SomeOtherClass
    {
        public function performSomeWork()
        {
            Signal::handle(SIGINT, function(Command $commandThatReceivedSignal) {
                $commandThatReceivedSignal->info('Received the SIGINT signal!');
            });
        }
    }
    
    // 3. Clearing handlers
    Signal::clearHandlers(SIGINT);
    // or
    Signal::clearHandlers();
  5. Handle signals using the SignalReceived event

    main

    Whenever a signal is received, the Spatie\SignalAwareCommand\Events\SignalReceived event is dispatched.

    Requirements:

    1. The command must define the $handlesSignals property to include the signal you want to listen for.
    2. You can then use Laravel's Event::listen to catch the event.

    Inside the listener, you can access the signal number via $event->signal and the command instance via $event->command. You can also use Spatie\SignalAwareCommand\Signals::getSignalName($signalNumber) to get a human-readable name for the signal.

    use Spatie\SignalAwareCommand\SignalAwareCommand;
    use Spatie\SignalAwareCommand\Events\SignalReceived;
    use Spatie\SignalAwareCommand\Signals;
    use Illuminate\Support\Facades\Event;
    
    class YourCommand extends SignalAwareCommand
    {
        protected $signature = 'your-command';
        protected $handlesSignals = [SIGINT];
    
        public function handle()
        {
            Event::listen(function (SignalReceived $event) {
                $signalNumber = $event->signal;
                $signalName = Signals::getSignalName($signalNumber);
                $event->command->info("Received the {$signalName} signal");
            });
    
            sleep(100);
        }
    }
  6. Register signal handlers with the Signal class

    main

    Use the handle() method to register a callback that should be executed when a specific system signal is received. The callback receives the current Illuminate\Console\Command instance as its only argument.

    $signal->handle(SIGTERM, function (Command $command) {
        // Perform cleanup logic
    });
    $signal->handle(int $signal, callable $callable): self
  7. Convert between signal names and signal numbers using the Signals class

    main

    The Spatie\SignalAwareCommand\Signals class provides utility methods to translate between human-readable signal names (e.g., SIGINT, SIGTERM) and their corresponding integer values using the PHP pcntl constants. This is useful if you need to programmatically identify or work with specific system signals within your command logic.

    use Spatie\SignalAwareCommand\Signals;
    
    // Get the name from a number
    $name = Signals::getSignalName(2);
    // Returns 'SIGINT'
    
    // Get the number from a name
    $number = Signals::getSignalForName('SIGTERM');
    // Returns 15
  8. Execute registered signal handlers

    main

    The executeSignalHandlers() method triggers all callbacks registered for a specific signal. You must pass the current Illuminate\Console\Command instance to the method so it can be passed to the registered handlers.

    $signal->executeSignalHandlers(SIGTERM, $this);
    $signal->executeSignalHandlers(int $signal, Command $command): self
  9. Use the Signal facade to interact with signals

    main

    The Signal facade provides a convenient way to access the Signal service within your Laravel application. It acts as a proxy to the Spatie\SignalAwareCommand\Signal class, allowing you to interact with signal-aware logic using Laravel's standard facade pattern.

    use Spatie\
    SignalAwareCommand\\Facades\\Signal;
    
    // Example usage of the Signal facade
    Signal::someMethod();