I'm using Heroku to host a Lumen app. I've setup the logging to send messages to stdout:
// bootstrap/app.php
$app->configureMonologUsing(function ($monolog) {
/** #var Monolog\Logger $monolog */
$monolog->pushHandler(new \Monolog\Handler\StreamHandler('php://stdout', \Monolog\Logger::DEBUG));
});
I've tested this works by adding a log message to the schedule function
protected function schedule(Schedule $schedule)
{
\Log::info('Running cronjobs.');
$schedule
->command('update:daily')
->timezone('America/Los_Angeles')
->everyMinute();
}
The Heroku logs show:
Jan 19 09:42:15 service app/scheduler.4140: [2018-01-19 17:42:14] lumen.INFO: Running cronjobs. [] []
Jan 19 09:42:15 service app/scheduler.4140: Running scheduled command: '/app/.heroku/php/bin/php' artisan update:daily > '/dev/null' 2>&1
However the update:daily command has a number of log messages inside it and none of them are showing up.
I thought this might be because of the > '/dev/null' so I tried adding ->sendOutputTo('php://stdout') and ->sendOutputTo(base_path('storage/logs/cronjobs.log')) to the scheduled task but neither works.
Here's my Procfile:
web: vendor/bin/heroku-php-nginx -C heroku-nginx.conf -l storage/logs/cronjobs.log public/
Ethan is right with his observation regarding > '/dev/null'. As Heroku collects logs from stdout and stderr - scheduled tasks are not being logged correctly.
Luckily there's a simple workaround: log to a file, and output it's content into stdout. Heroku will then be able to log everything, whether using its native logging or using an add-on like LogDNA, Papertrail, etc.
Given that you're logging to a single channel in logging.php, into the file storage/logs/laravel.log, replace your scheduler command php artisan schedule:run with the following:
touch ./storage/logs/laravel.log; tail -f ./storage/logs/laravel.log & php artisan schedule:run
What it does?
Makes sure a log file exists. If it didn't - the following command will fail
Tails the log file, so its content is outputted to stdout
Starting the Laravel scheduler
The advantage of using this method is that you don't need to change your code, rather the configuration and the environment, so if you're running the app on other platforms - it won't change the way they work/log.
Laravel uses the > '/dev/null' when you do not call ->sendOutputTo(). I couldn't figure out an appropriate way to use the ->sendOutputTo() function to send to stdout.
What I did to fix this issue was change the ->command() function to a ->call(function(){}) function and executed the same single line of code the terminal command could have called. When laravel calls a Closure, it does not dump the output to > '/dev/null'.
Related
I have a Laravel App with Short Schedule package installed and a crontab to execute it.
Inside the executed method I have a SHELL_EXEC function with some code inside it.
The problem is that when the code runs automatically using the cron, the SHELL EXEC doesn't work. The output is null.
When I run the method directly using php artisan or by simply running the schedule using php artisan manually, it works.
To have a clear vision of what's going on:
Inside the crontab -e I have the following
* * * * * php /var/www/html/project/artisan short-schedule:run --lifetime=60
The cron executes this method which has the following code:
$shell_command = '/home/paul/elrondsdk/erdpy --verbose tx new --receiver xxxx --send --pem asdfa.pem --gas-limit 300 --nonce 12';
$output = shell_exec($shell_command);
Log::info('output', [$output]);
If it runs automatically using the cron, the $output is NULL.
If I run the command manually, I get a proper output.
Initially I thought I need to specify the exact path in the shell exec because cron doesn't not PATH. Unfortunately did not solve my problem.
Thanks!
I tried to run the command manually or to run php artisan schedule:run and wait and it worked!
It doesn't work ONLY when its runs by the cron.
I am currently working on a Symfony 6 project. Now I have the situation that I want to stop and start a systemd service which is used to consume the messages from the Symfony Messenger message queue.
The service is called "messenger-worker#.service" and is located under /etc/systemd/system
Now in my PHP script I run the following:
$output = shell_exec("sudo -u www-data /usr/bin/systemctl stop messenger-worker#1.service 2>&1");
dd($output)
The $output contains the following error message:
Failed to stop messenger-worker#1.service: Interactive authentication required.
See system logs and 'systemctl status messenger-worker#1.service' for details.
Under /etc/sudoers.d I already created a file called "www-data". With the following code:
%www-data ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop messenger-worker#1.service
Does anyone have an idea what I am doing wrong here?
As #Rufinius noted in the comments. It does not make sence to try to execute the command as -u www-data. Furthermore I realized that I had to remove "2>&1" at the end of the command in order to make it work properly. I think it's because I didn't include the part ("2>&1") in my sudoers.d file in the command, but I don't need it now anyway. So I adjusted it as the following:
shell_exec("sudo /usr/bin/systemctl stop messenger-worker#1.service");
I am trying to schedule a task in windows task scheduler what i want is have to run a url every 5 minutes without opening browser i tried using
php -f http://localhost/sms/test.php
wget -q -O - http://localhost/sms/test.php > tmp.txt
and also the full path
php -f C:/Bitnami/redmine-2.4.3-0/apache2/htdocs/sms/test.php
it shows the same error
Task Scheduler failed to start instance
"{a889332e-87f0-421b-accc-4ff19ae98599}" of "\test" task for user
"PUGOSTECH\xxxxx" . Additional Data: Error Value: 2147942402.
I understand that i am making a silly mistake to create scheduler but dont know how to find?
If i use by opening browser command it works fine like
cmd /c start http://localhost/sms/test.php
I have a command scheduled in the Laravel 5.4 scheduler and would like to start the Laravel cron on Mac OS X El Capitan.
app/Console/Kernel.php
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
protected $commands = [
'App\Console\Commands\GetToken'
];
protected function schedule(Schedule $schedule) {
$schedule->command('gettoken')->everyMinute();
}
protected function commands() {
require base_path('routes/console.php');
}
}
My GetToken.php makes an API call and then a DB change. I believe that this is working properly, as I can run the task directly from the cli using:
php /path/to/project/artisan schedule:run 1>> /dev/null 2>&1
To edit my cron file I use:
env EDITOR=nano crontab -e
I then add:
* * * * * php /path/to/project/artisan schedule:run >> /dev/null 2>&1
I save with ctrl+o and exit with ctrl+x.
Re-editing the file shows that the changes have saved.
Running crontab -l shows the text that I entered into the crontab file.
My cron never runs. I can only get it to run once by running manually using the command I mentioned above.
Not directly answering your question, but proposing another solution:
If you want to set up cron jobs for your development environment, it's best to use Homestead, for its Linux standards compliance.
For small projects that i develop directly inside macOS, i run the following command inside the project root (in a separate terminal tab) to have my jobs run every minute:
while true; do php artisan schedule:run; sleep 60; done
This helps to make sure, the cron jobs are only run while i'm developing. When i'm done, i Ctrl+C that command and can be sure nothing unexpected happens while i'm not watching.
Plus it gives me the freedom to adjust the interval, by simple choosing another number of seconds for the sleep command. This can save time when developing.
Update Laravel 8.x
Laravel now offers the above as a single artisan command:
php artisan schedule:work
I have an external PHP script, that is processing an XML array to insert, update or delete rows in a database. This script lies in the root of the project in a folder called scripts and I can run and execute it via terminal with no problems whatsoever and it updates the database accordingly:
php index.php
I have also set up a schedule in Laravel (using October CMS syntax)
public function registerSchedule($schedule)
{
$schedule->exec(public_path() . '/script/index.php')->everyMinute();
}
This however is doing nothing. I tried manually running the schedule with artisan in command line by:
php artisan schedule:run
And the output is
Running scheduled command: /Users/x/x/x/x/scripts/index.php > '/dev/null' 2>&1 &
Nothing happens in the database tho.
Did you try to generate a new key?
php artisan generate:key