How to keep Laravel Queue system running on server

前提是你 提交于 2019-11-27 02:50:47

Running

nohup php artisan queue:work --daemon &

Will prevent the command exiting when you log out.

The trailing ampersand (&) causes process start in the background, so you can continue to use the shell and do not have to wait until the script is finished.

See nohup

nohup - run a command immune to hangups, with output to a non-tty

This will output information to a file entitled nohup.out in the directory where you run the command. If you have no interest in the output you can redirect stdout and stderr to /dev/null, or similarly you could output it into your normal laravel log. For example

nohup php artisan queue:work --daemon > /dev/null 2>&1 &

nohup php artisan queue:work --daemon > app/storage/logs/laravel.log &

But you should also use something like Supervisord to ensure that the service remains running and is restarted after crashes/failures.

You should use linux supervisor

Installation is simple and on Ubuntu I can install it with following command:

apt-get install supervisor

Supervisor configuration files are located in /etc/supervisor/conf.d directory.

[program:email-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/laravel-example/artisan queue:work redis --queue=emailqueue --sleep=3 --tries=3
autostart=true
autorestart=true
user=forge
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/laravel-example//storage/logs/supervisord.log

For each process you should create a new process configuration file. With this configuration, listener will retry each job 3 times. Also Supervisor will restart listener if it fails or if system restarts.

zeros-and-ones

The command

nohup php artisan queue:work --daemon &

was correct, it would allow the process to continue after closing the SSH connection; however, this is only a short term fix. Once your server is rebooted or any issue causes the process to stop you will need to go back and run the command again. When that occurs, you never know. It could happen on a Friday night, so it is better to implement a long term solution.

I ended up switching over to Supervisord, this can be installed on Ubuntu as easy as

sudo apt-get install supervisor 

For AWS-AMI or RedHat users you can follow the set of instructions I outlined in this question:

Setting up Supervisord on a AWS AMI Linux Server

From https://gist.github.com/ivanvermeyen/b72061c5d70c61e86875

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class EnsureQueueListenerIsRunning extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'queue:checkup';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Ensure that the queue listener is running.';

    /**
     * Create a new command instance.
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function handle()
    {
        if ( ! $this->isQueueListenerRunning()) {
            $this->comment('Queue listener is being started.');
            $pid = $this->startQueueListener();
            $this->saveQueueListenerPID($pid);
        }

        $this->comment('Queue listener is running.');
    }

    /**
     * Check if the queue listener is running.
     *
     * @return bool
     */
    private function isQueueListenerRunning()
    {
        if ( ! $pid = $this->getLastQueueListenerPID()) {
            return false;
        }

        $process = exec("ps -p $pid -opid=,cmd=");
        //$processIsQueueListener = str_contains($process, 'queue:listen'); // 5.1
        $processIsQueueListener = ! empty($process); // 5.6 - see comments

        return $processIsQueueListener;
    }

    /**
     * Get any existing queue listener PID.
     *
     * @return bool|string
     */
    private function getLastQueueListenerPID()
    {
        if ( ! file_exists(__DIR__ . '/queue.pid')) {
            return false;
        }

        return file_get_contents(__DIR__ . '/queue.pid');
    }

    /**
     * Save the queue listener PID to a file.
     *
     * @param $pid
     *
     * @return void
     */
    private function saveQueueListenerPID($pid)
    {
        file_put_contents(__DIR__ . '/queue.pid', $pid);
    }

    /**
     * Start the queue listener.
     *
     * @return int
     */
    private function startQueueListener()
    {
        //$command = 'php-cli ' . base_path() . '/artisan queue:listen --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.1
        $command = 'php-cli ' . base_path() . '/artisan queue:work --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.6 - see comments
        $pid = exec($command);

        return $pid;
    }
}

For those who are already running NodeJS on their production environments. I use PM2 to manage app processes.

# install
npm install -g pm2

# in project dir with your CI or dev setup tool 
# --name gives task a name so that you can later manage it
# -- delimits arguments that get passed to the script
pm2 start artisan --interpreter php --name queue-worker -- queue:work --daemon

I use Vagrant in development and setup NodeJS and this process using only inline vagrant scripts.

When you use PM2 in development you can use one of the many watchers to manage the restart. Simply run pm2 restart queue-worker when you pick up a change. In production I don't recommend this approach, rather opt for a build tool that can follow this process.

# 1. stop pm task to ensure that no unexpected behaviour occurs during build
pm2 stop queue-worker
# 2. do your build tasks
...
# 3. restart queue so that it loads the new code
pm2 restart queue-worker

The best way is PM2 (Advanced, production process manager for Node.js) that you can monit your queues and see their's logs.

with command below in your project directory, run queue worker :

pm2 start artisan --name laravel-worker --interpreter php -- queue:work --daemon

What if you start the listening within a screen? See here: http://aperiodic.net/screen/quick_reference Then even if you log out, the screen would still be active and running. Not sure why the daemonization doesnt work though.

Using pm2

I had JS script running with pm2 (Advanced, production process manager for Node.js) Which was the only one I was running. But now as I got one more process to keep running.

I created process.yml to run both with a single command. Check the first one would run php artisan queue: listen

# process.yml at /var/www/ which is root dir of the project
apps:
  # Run php artisan queue:listen to execute queue job
  - script    : 'artisan'
    name      : 'artisan-queue-listen'
    cwd       : '/var/www/'
    args      : 'queue:listen' # or queue:work
    interpreter : 'php'

  # same way add any other script if any.

Now run:

> sudo pm2 start process.yml

Check more options and feature of pm2

Since this was a Laravel-specific question, I thought I would suggest a Lravel-specific answer. Since you are already using cronjobs on this server, I would recommend that you set up the shell command as a recurring cronjob to always verify that the worker is running. You could either set up the shell command to run natively through cron on your server, or you could use the Laravel console kernel to manage the command and add logic, such as checking whether you already have a worker running and, if not, go ahead and start it back up.

Depending on how often you need to run your command, you could do this as infrequently as once a week, or even once a minute. This would give you the ability to make sure that your workers are continuously running, without having to add any overhead to your server, such as Supervisor. Giving permissions to a 3rd party package like supervisor is ok if you trust it, but if you can avoid needing to rely on it, you may want to consider this approach instead.

An example of using this to do what you want would be to have a cronjob that runs each hour. It would execute the following in sequential order from within a custom Laravel console command:

\Artisan::call('queue:restart');

\Artisan::call('queue:work --daemon');

Note that this applies for older versions of Laravel (up to 5.3) but I haven't tested on newer versions.

You can use monit tool. it's very small and useful for any type of process management and monitoring.

After Downloading binary package from this link, you can extract it to a folder on your system and then copy two files from the package to your system to install it:

cd /path/to/monit/folder
cp ./bin/monit /usr/sbin/monit
cp ./conf/monitrc /etc/monitrc  

Now edit /etc/monitrc base on your needs(reference doc). then create a init control file to enable monit on startup. now start monit like this:

initctl reload-configuration
start monit

1)sudo apt install supervisor or

sudo apt-get install supervisor

2)cd /etc/supervisor/conf.d 3)create new file inside

sudo vim queue-worker.conf

File Content

[program:email-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/laravelproject/artisan queue:work
autostart=true
autorestart=true
user=root
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/html/laravelproject/storage/logs/supervisord.log

4)sudo supervisorctl reread

when run this command get output queue-worker:available

5)sudo supervisorctl update

when run this command get output queue-worker:added process group

other command

1)sudo supervisorctl reload

when run this command get output Restarted supervisord

2)sudo service supervisor restart

I simply used php artisan queue:work --tries=3 & which keeps the process running in the background. But it sometimes stops. I don't know why this is happening

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!