Kdyby/Console a puštené cronu
- wicked
- Člen | 290
Zdravím Vás,
mám menší dotaz, jak mám nastavit do cronu aby pustilo danou věc?
Mám CronCommand.php
<?php
namespace App\Console;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Nette;
use App\Model;
use Nette\Mail\SmtpMailer;
use Nette\Mail\Message;
use Tracy\Debugger;
class CronCommand extends Command {
/** @var \App\Model\CronModel @inject */
public $cron;
protected function configure() {
$this->setName('cron')->setDescription('Zápis cron úloh');
}
protected function execute(InputInterface $input, OutputInterface $output) {
try {
$cron = $this->cron->findAll();
foreach ($cron as $c) {
if ($c->start == new Nette\Utils\DateTime()) {
try {
$mail = new Message();
$mail->setFrom('info@jirickajakub.cz');
$mail->addTo('jiricka.kuba@gmail.com');
$mail->setSubject('Pokus cron emailu');
$mail->setBody('A obsah který už jeeee! :)' . new Nette\Utils\DateTime());
$mailer = new Nette\Mail\SendmailMailer();
$mailer->send($mail);
} catch (Nette\Mail\SmtpException $ex) {
Debugger::log($ex, Debugger::ERROR);
throw $ex;
}
}
}
$output->writeLn('<info>[OK] - cron</info>');
return 0; // zero return code means everything is ok
} catch (\Exception $exc) {
$output->writeLn('<error>cron - ' . $exc->getMessage() . '</error>');
return 1; // non-zero return code means error
}
}
}
Když to pustím normálně na serveru (vlastní server) pomocí
php /var/www/index.php cron
Tak vše jede jak má, ale zaboha mě nejde to pustit automaticky pomocí cronu …
Zkoušel jsem crontap -e a nastavit to samé co tady, nic se neprovedlo ( ani když jsem dal do else větve to samé, aby mě aspoň chodilo něco …)
Dále jsem to zkoušel přec ISPConfig cron ale také nic …
Jak to mám správně tedy odkazovat?
Mockrát děkuji :)
ještě config:
extensions:
console: Kdyby\Console\DI\ConsoleExtension
console:
url: http://mailer.jirickajakub.cz
commands:
- App\Console\CronCommand
Editoval wicked (1. 3. 2015 12:09)
- wicked
- Člen | 290
Už vím kde je error …
problém nastává zde
$datetime = new Nette\Utils\DateTime();
foreach ($cron as $c) {
if ($c->start == $datetime) {
Respektivě když to mám vytvořeno tahle, datum dosazen do $datetime tak to nic neudělá …
ale jakmile jej zapíši natvrdo
$c->start == '2014-03-01 14:28:00'
Tak to vše proběhne … $datetime je ve zprávném formátu jako záznam v DB …
Vůbec mě nenapadá, kde může být chyba…
- wicked
- Člen | 290
Od té podmínky očekávám to, že když čas v DB bude stejny jako aktualni cas, který beru pomoci new Nette\Utils\DateTime() tak se provede ta podmínka …
v DB je start normalne datetime a ma stejny format ktery by mel byt …
jak jinak by jsi chtel udelat to, aby se ti ten mail poslal jenom v tu dobu, kterou mas nastavenou v DB?
a proc me to ted funguje tak, ze me chodi email kazdou minutu, kdyz se ta podminka nerovna zaznamu v DB?
Editoval wicked (1. 3. 2015 19:15)
- Filip Klimeš
- Nette Blogger | 156
Co takhle porovnávat místo dvou objektů stringy?
$now = new \Nette\Utils\DateTime();
if ($c->start->format('Y-m-d H:i') === $now->format('Y-m-d H:i')) { ... }
Jak často pouštíš CRON? Tohle Ti podle mě bude zbytečně vytěžovat server. Lepší by možná bylo místo DB napsat různé commandy pro různé akce a čas si pak nastavit v crontabu.
- Filip Procházka
- Moderator | 4668
A nebylo by lepší mít několik různých commandů, kde každý by měl jiný úkol a v crontabu by sis nastavil, který se má kdy spouštět?
- wicked
- Člen | 290
Bohužel mě nenapadá jak řešit to co potřebuji.
V db mám uložen záznam cronu, který obsahuje čas a to, co má provést.
Jedná se o rozesílání emailových kampaní v určitý čas na určitě adresy s určitou kampaní, takže čas je zde nutný takto dodržovat.
Vem si, že budu rozesílat 5 kampaní a každá bude v jiném čase, proto to mám řešeno takto :)
Pokud Vás napadne něco jiného, rád se poučim :)
- llook
- Člen | 407
Nefungovalo ti to proto, že v DB máš čas třeba 12:00, ale aktuální čas je třeba 12:00:01.
Lepší by bylo porovnávat, jestli čas z DB je mezi aktuálním časem a časem posledního spuštění toho cronu (někam si ten čas ukládat), protože co když ti to pár minut z jakéhokoli důvodu nepojede? Je žádoucí, aby v takovém případě naplánovaná akce vůbec neproběhla?
- leninzprahy
- Člen | 150
Mě přijde jednodušší mít v db, krom času kdy se to má provést, i příznak jestli se to provedlo (třeba jako datum odeslání). V tom Commandu pak najdeš všechny záznamy, které už se měly odeslat, ale ještě nejsou odeslané (WHERE start < NOW() AND sent IS NULL), ty zpracuješ a nastavíš jim příznak odeslání (sent = NOW()).
Pak ten cron můžeš spouštět jak často potřebuješ, a on ti zpracuje, jen to co má…
- leninzprahy
- Člen | 150
Nepřijde mi jako dobrý nápad spoléhat na to, že když máš v db uložen čas spuštění např. 13:30:00, že se i ten command provede přesně ve 13:30:00. Stačí, když se spustí v 13:30:02, a už se nic nepošle…
- wicked
- Člen | 290
Jenže já to v DB právě měl uložené také pomocí
Nette\Utils\Datetime(), takže i DB byla ve stylu
2015-03-30 15:00:01
V tom problém nebyl :)
Jinak vyřešené to mám tak, že když se ta cron úloha neprovede, hodí to error do adminu a upozorní na neúspěšné spuštění, takže bude již na obsluze, aby jej nastavila znovu
- leninzprahy
- Člen | 150
Zápis v cronu * * * * * * * ale znamená každou minutu, ne pořád! A nikdo ti nezaručí, že se spustí přesně v 2015–03–30 15:00:01, může se spustit 2015–03–30 15:00:03, nebo taky 2015–03–30 15:00:04 a pak už ti ta podmínka neprojde…
- leninzprahy
- Člen | 150
A co zkusit to
označování za odeslané ?
Z výhod například:
- Vyhneš se procházení všech historických i budoucích záznamů, protože si vybereš jen ty, které je zrovna potřeba rozeslat,
- když se stroj z nějakého důvodu zasekne, po spuštění automaticky provede to, co mělo být provedeno,
- můžeš zkontrolovat, co a kdy se doopravdy provedlo.