Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jobs execute just once. #49

Closed
mockingbirdnj83 opened this issue Dec 4, 2014 · 7 comments
Closed

Jobs execute just once. #49

mockingbirdnj83 opened this issue Dec 4, 2014 · 7 comments
Assignees
Labels

Comments

@mockingbirdnj83
Copy link

Hello,

I have a script checking errors on webpages. I'm trying to develop a tool with Laravel to manage 'alerts' (automated calls to this script to maintain a surveillance).
But I'm a bit confused about how to using your lib.

When I add a cron like this :

Route::get('/crontest', function() {
        Cron::add('example1', '* * * * *', function() {
               return 'Example 1 ran';
        });    
        $report = \Liebig\Cron\Cron::run();
        var_dump($report);
});

I get a new line in cron_manager like this :
| 719 | 2014-12-04 14:29:02 | 0.00 |

And a new line in cron_jobs like this :
| 11 | example1 | Example 1 ran | 0.00 | 719 |

But nothing else. As far as I understand, I should have a new line in cron_manager every minutes. But I don't.

Must I use Event::listen('cron.collectJobs') to add crons ? What does it concretely do ?
Can I call Cron::add everywhere in the app ?

Sorry for my mistakes, English isn't my native language.

Thank you in advance.

@liebig
Copy link
Owner

liebig commented Dec 5, 2014

Hello mockingbirdnj83,

Thanks for using Cron. Please follow the README. Since version 1 of Cron you can use a build in route and don't have to create a own route. For this you can define your jobs in the /path/to/laravel/app/start/global.php file like

Event::listen('cron.collectJobs', function() {
    Cron::add('example1', '* * * * *', function() {
                    // Do some crazy things unsuccessfully every minute
                    return 'No';
                });

    Cron::add('example2', '*/2 * * * *', function() {
        // Do some crazy things successfully every two minute
        return null;
    });

    Cron::add('disabled job', '0 * * * *', function() {
        // Do some crazy things successfully every hour
    }, false);
});

Now please generate a route security key via php artisan cron:keygen and save this to the config file. Now you need for example an online cronjob service which runs this route (http://exampledomain.com/cron.php?key=YOURKEY) every minute. In comparison to a Java application server for example, PHP only runs if it is executed. If crontab or an online cronjob service provider calls PHP and starts the application, Cron can execute the jobs and will start the work. If PHP is not started, the application sleeps and nothing happens.

After this is done you should have a new line in the cron_manager table every minute.

Best Regards,
Marc

@liebig liebig added the question label Dec 5, 2014
@liebig liebig self-assigned this Dec 5, 2014
@mockingbirdnj83
Copy link
Author

Thanks to answer me so quickly.
Yes, I read the README a lot of time before posting this issue.
It works when I do it in global.php. But I want to automate the Cron creation. I can't do this by hand.

Let me explain : I have a form with fields corresponding to the parameters of my script. When I get these datas from the form, I would like to open a Cron that create a command line with them, and use shell_exec() to call my script with this command line. (I have shell access).

Something like this :

Cron::add('alert8', $pattern, function($parameter) {
    $cmd = './script/main.php';
    if ($parameter->foo == 1) {
        $cmd += ' -foo';
    } else if ($parameter->bar) {
        $cmd += " -bar $parameter->bar";
    }
    exec($cmd);
    return null;
}, true);

If I must use Cron:add in global.php I can't automate the Cron creation (without opening and writing in the file with php. And I would like to avoid this). It's why I'm wondering if there is a way to call Cron:add elsewhere than global.php ?

@liebig
Copy link
Owner

liebig commented Dec 8, 2014

Okay I understand that you want to add Cron jobs dynamically. But I don't understand the way you do this. If you send the form, you will add a Cron job and you will start Cron. After this is done and the request is handled, PHP will shut down and delete all the memory. So your added Cron job is gone because it is only added to the memory at runtime. For that reason you have to save the dynamic Cron job information somewhere else. I would recommend a database for this.

For dynamic Cron jobs your database table cron_definitions should have the fields ID, NAME, EXPRESSION and FUNCTION. Now add to the /path/to/laravel/app/start/global.php file something like

Event::listen('cron.collectJobs', function() {
    // TODO Run through cron_definitions via foreach and execute
    Cron:add($name, $expression, function() use ($function) {
        $return = eval($function);
        if ($return === FALSE) {
            return 'Parse Error of function ' . $function;
        } else {
            return $return;
        }
    });
});

Now you can use Crons build in route or the artisan command artisan cron:run to run the Cron job execution every minute. With a formular and a Laravel route you can create, read, update and delete the jobs dynamically.

Please note that the eval function could be a security risk.

I hope this helps.

Best Regards,
Marc

@mockingbirdnj83
Copy link
Author

Hello Liebig. Thanks a lot for your answers.

I understand what you said about the memory. And your idea is very relevant. It's definitely what I need.
I just have a quick question, what does that do ? :

function() use ($function)

I never seen this before.

One more time, thanks.
You really helped me.

@liebig
Copy link
Owner

liebig commented Dec 10, 2014

Hi mockingbirdnj83,
You are welcome. My variable names are poor. The $name, $expression and $function variables came from the database. You need these for Cron. You add the $function string to the anonymous function, which will be called if the expression matchs the current timestamp. This anonymous function will execute the $function via eval. So you need use to pass the database function string to the anonymous function with function() use ($function) {. You can read more about anonymous functions here. I hope this helps you.

@mockingbirdnj83
Copy link
Author

Hello Liebig,
Thanks to you I was able to do what I want.
Your tool is great, and your help too.

Thanks again for it and for all your efforts.

Thomas.

@liebig
Copy link
Owner

liebig commented Dec 15, 2014

Hi Thomas,
Thanks for your feedback. You are welcome!

Best Regards
Marc Liebig

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants