symfony2命令被杀未知原因

时间:2015-04-05 04:24:06

标签: php symfony doctrine

我用flock

每秒都有一个sms cronjob与我的服务器一起运行

我的脚本被杀了异常,为什么我说这是异常?

有时,我的脚本运行并发送大约2千条短信没有任何问题

某个时候(现在),我的脚本运行一个新的批次,有173个短信,并且总是随机被杀

这是调度员

<?php
namespace MPN\Sms2Bundle\Service;

use Doctrine\ORM\EntityManager;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use MPN\CRMBundle\Service\UserAwareService;
use MPN\Sms2Bundle\Service\Calculator;
use MPN\Sms2Bundle\Service\Renderer;
use MPN\Sms2Bundle\Manager\SettingManager;
use MPN\DataBundle\Entity\Contact\Contact;
use MPN\DataBundle\Entity\Contact\Phone as ContactPhone;
use MPN\Sms2Bundle\Entity\Sms;
use MPN\Sms2Bundle\Entity\SmsConstants;
use MPN\Sms2Bundle\Entity\Batch;
use MPN\Sms2Bundle\Entity\History;
use MPN\Sms2Bundle\SmsEvents;
use MPN\Sms2Bundle\Event\FailureEvent;

/**
 * This class provides low-level methods for sending `sms`.
 *
 * @see \MPN\Sms2Bundle\Service\Sender::sendNow() for high-level method
 */
class Dispatcher extends UserAwareService
{
    private $em;
    private $eventDispatcher;
    private $calculator;
    private $renderer;
    private $settingManager;
    private $username;
    private $password;
    private $sender;

    public function __construct(EntityManager $em, EventDispatcherInterface $eventDispatcher, SettingManager $settingManager, Calculator $calculator, Renderer $renderer, SecurityContextInterface $securityContext, $username, $password, $sender)
    {
        $this->em = $em;
        $this->eventDispatcher = $eventDispatcher;
        $this->settingManager = $settingManager;
        $this->calculator = $calculator;
        $this->renderer = $renderer;
        $this->username = $username;
        $this->password = $password;
        $this->sender = $sender;
        $this->setSecurityContext($securityContext);
    }

    /**
     * Sends $sms to $contactPhone.
     *
     * You should check if credit is sufficient before sending $sms.
     * This method ignores the contact's status, i.e. if it is soft-deleted.
     *
     * @see \MPN\Sms2Bundle\Service\Calculator::hasEnoughCreditForOneTime() for checking credit balance
     * @param string|ContactPhone $contactPhone
     * @return boolean|integer Credit spent or FALSE if failed to send.
     */
    public function send(Sms $sms, $contactPhone)
    {
        if (is_string($contactPhone)) {
            $mobile = $contactPhone;
            $contact = null;
        } else {
            $mobile = $contactPhone->getNumber();
            $contact = $contactPhone->getContact();
        }

        $content = $this->renderer->render($sms, $contact);

        $credit = false;
        if ($this->_send($mobile, $content))
            $credit = $this->calculator->calculateCredit($sms, $contact);

        return $credit;
    }

    /**
     * Sends $sms to all filtered and non-deleted linked contact phones.
     * Credits are *DEDUCTED* here.
     *
     * You should check if credit is sufficient to send $sms.
     *
     * @see \MPN\Sms2Bundle\Service\Calculator::hasEnoughCreditForOneTime() for checking credit balance
     * @param \MPN\Sms2Bundle\Entity\Sms $sms
     * @param boolean                    $andFlush
     */
    public function sendToAll(Sms $sms, $andFlush = true)
    {
        $recipients = array();

        if ($sms->getToAllContactTypes() || $sms->getToAllContactGroups() || $sms->getToAllContactPhones()) {
            $contacts = $this->em->getRepository('MPN\DataBundle\Entity\Contact\Contact')->findBy(array(
                'deleted' => false,
            ));

            foreach ($contacts as $contact)
                $recipients = array_merge($recipients, $contact->getMobilePhones());
        } else {
            $contactTypes = $sms->getContactTypes();
            foreach ($contactTypes as $contactType)
                $recipients = array_merge($recipients, $contactType->getMobilePhones());

            $contactGroups = $sms->getContactGroups();
            foreach ($contactGroups as $contactGroup)
                $recipients = array_merge($recipients, $contactGroup->getMobilePhones());

            $contactPhones = $sms->getContactPhones();
            foreach ($contactPhones as $contactPhone)
                $recipients[] = $contactPhone;

            $company = $sms->getCompany();
            if (null !== $company && $company->hasContacts()) {
                $recipients = array_merge($recipients, $company->getMobilePhones());
            }
        }

        $recipients = array_unique(array_merge($recipients, $sms->getGeneralContactsAsArray()));

        // Create a Batch instance and *flush*
        $batch = new Batch();
        $batch->setDeliveredAt(new \DateTime());
        $sms->addBatch($batch); // add batch increase sentCount by 1
        $this->em->flush();

        $failedContacts = array();
        foreach ($recipients as $contactPhone) {
            $isContactPhoneInstance = $contactPhone instanceof ContactPhone;

            if ($isContactPhoneInstance) {
                $contact = $contactPhone->getContact();

                if (!$this->isOwner($contact)
                    || $contact->isDeleted()
                    || !$sms->testTargetContact($contact)) {
                    continue;
                }

                //Check if not mobile number, mean not start with 601, skip it
                // if (substr($contact->getPhone(), 0, 3) != '601') {
                    // continue;
                // }
            }

            $credit = $this->send($sms, $contactPhone);
            print ".";
            $isSuccessful = $credit !== false;
            $history = new History();

            if ($isContactPhoneInstance) {
                $contact = $contactPhone->getContact();
                $content = $this->renderer->render($sms, $contact);
                $history
                    ->setRecipientName($contact->getFullName())
                    ->setRecipientNumber($contactPhone->getNumber())
                ;
            } else {
                $content = $this->renderer->render($sms);
                $history
                    ->setRecipientName('General Contact')
                    ->setRecipientNumber($contactPhone)
                ;
            }

            // Notify listeners to handle this failure
            if ($isContactPhoneInstance && !$isSuccessful && !in_array($contact, $failedContacts)) {
                $event = new FailureEvent($sms, $contact, $content);
                $this->eventDispatcher->dispatch(SmsEvents::FAILURE, $event);

                // Record this contact so mail won't be sent more than one time
                $failedContacts[] = $contact;
            }

            $history
                ->setContent($content)
                ->setCredit((int) $credit)
                ->setSuccess($isSuccessful)
            ;

            $batch
                ->addHistory($history)
            ;

            $this->em->flush();

            // decrease the credit *now*
            // failed to send messages cost 0 credit, so doesn't matter!
            $this->settingManager->decreaseCredit($credit);
        }

        if ($andFlush)
            $this->em->flush();

        return $batch->getCredit();
    }

    /**
     * Sends a message without logging any information.
     *
     * @param string $mobile
     * @param string $content
     *
     * @return bool
     */
    public function quickSend($mobile, $content)
    {
        return $this->_send($mobile, $content);
    }

    /**
     * Actually sends the message out.
     *
     * @param string $mobile
     * @param string $content
     *
     * @return bool
     */
    private function _send($mobile, $content)
    {
        $url = $this->buildUrl($mobile, $content);
        $response = @file_get_contents($url);

        return !!preg_match('/^1701:\d+$/', $response);
    }

    private function buildUrl($mobile, $content)
    {
        // $url = 'http://www.example.com/websmsapi/isendsms.aspx?username=%s&password=%s&sender=%s&type=%d&mobile=%s&message=%s';

        // Fake sms server, record all the record only
        $url = 'http://example.my/sendsms.php?mobile=%s&message=%s';

        $encodedContent = $this->renderer->encode($content);

        if ($this->renderer->isUnicodeContent($content))
            $type = 3;
        else
            $type = 1;

        // return sprintf(
            // $url,
            // $this->username,
            // $this->password,
            // $this->sender,
            // $type,
            // $mobile,
            // $encodedContent
        // );

        return sprintf(
            $url, $mobile, $encodedContent
        );
    }
}

这是发送命令

<?php
namespace MPN\Sms2Bundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use MPN\Sms2Bundle\Entity\SmsConstants;
use MPN\Sms2Bundle\SmsEvents;

class SendCommand extends ContainerAwareCommand
{
    protected $preEventDispatched = false;

    protected function configure()
    {
        $this
            ->setName('sms:send')
            ->setDescription('Send SMS')
            ->addArgument('id', InputArgument::OPTIONAL, 'Sms ID')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        set_time_limit(1800);
        $container = $this->getContainer();

        $eventDispatcher = $container->get('event_dispatcher');
        $em = $container->get('doctrine')->getManager();
        $repo = $em->getRepository('MPNSms2Bundle:Sms');
        $queryBuilder = $repo->createQueryBuilder('s');

        $calculator = $container->get('mpn_sms2.calculator');
        $dispatcher = $container->get('mpn_sms2.dispatcher');

        $id = $input->getArgument('id');

        // In progress status and scheduled to send records
        $queryBuilder
            ->where('s.status = :status')->setParameter('status', SmsConstants::STATUS_IN_PROGRESS)
            ->andWhere('s.scheduledAt <= :now')->setParameter('now', new \DateTime())
            ->andWhere('s.sendCount > s.sentCount')
            ->orderBy('s.createdAt', 'ASC')
        ;

        $messages = array();
        if ($id) {
            $message = $queryBuilder
                ->andWhere('s.id = :id')->setParameter('id', $id)
                ->getQuery()
                ->getOneOrNullResult()
            ;

            if ($message)
                $messages[] = $message;
        } else {
            $messages = $queryBuilder->getQuery()->getResult();
        }

        $spentCredit = 0;
        foreach ($messages as $sms) {
            if ($sms->shouldSendNow() && $calculator->hasEnoughCreditForOneTime($sms)) {
                // Pre process event
                if (false === $this->preEventDispatched) {
                    $eventDispatcher->dispatch(SmsEvents::PRE_PROCESS);
                    $this->preEventDispatched = true;
                }

                // credits are deducted in dispatcher
                $credit = $dispatcher->sendToAll($sms, false);
                $spentCredit += $credit;

                $em->flush();
            }
        }

        $output->writeln(sprintf(
            'Spent %d credit(s) at %s',
            $spentCredit,
            date('d-m-Y h:i:s a', time())
        ));

        // Post send event
        $eventDispatcher->dispatch(SmsEvents::POST_PROCESS);
    }
}

在我的php设置中,我有

  

max_execution_time = 480

     

max_input_time = 0

     

max_input_vars = 1000

     

memory_limit = 4096M

这里是cronjob

/usr/bin/env php /home/ecocrm/public_html/control/app/console sms:daemon -e prod >> /tmp/ecocrm_sms_daemon.log 2>&1

我将msg保存在日志中,所以我可以回来看看

在我的调度员中,每次成功(或失败)

  

打印“。”;

我检查了我的日志文件,有.......... Killed

有时.......................已经杀了

我怎样才能检查杀人的原因?任何我应该如何修复或调试它,错误信息是如此简单,只是 Killed ,没有其他的消息让我检查它...如果你想了解更多有关源代码的信息,请告诉我,非常感谢谁为此提供帮助,首先感谢

**update 1:**
在我google一段时间之后,很多人说它错误因为内存泄漏,所以我添加了这个

print(sprintf('Memory usage (currently) %dKB/ (max) %dKB', round(memory_get_usage(true) / 1024), memory_get_peak_usage(true) / 1024));print("\r\n");

在调度员 foreach($ recipients as $ contactPhone){

这是结果

Memory usage (currently) 114432KB/ (max) 114688KB
Memory usage (currently) 114432KB/ (max) 114688KB
Memory usage (currently) 114432KB/ (max) 114688KB
Memory usage (currently) 114432KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB
Memory usage (currently) 114688KB/ (max) 114688KB

0 个答案:

没有答案