繁体   English   中英

如何停止PHP脚本? 阻止发送电子邮件?

[英]How to stop a PHP script ? Prevent emails to be sent?

我有一个PHP应用程序(使用LAMP堆栈),可以发送数千个应用程序。 我很乐意停止发送电子邮件。 我显然不能通过关闭浏览器来停止感觉。

我应该杀死进程,还是有其他方法可以杀死进程? 我应该杀死哪个过程? 可能不止一个..?

PS:当然,该应用程序的设计不正确。..但这不是问题。

如果它是您自己的(自行编写的)应用程序,则可能应该添加一些功能,以使您可以暂停或暂停执行。

一个示例是每X次迭代一次,脚本将检查资源以获取命令。 如果资源队列中有命令,它将按顺序执行它们,将其删除并继续(如果适用)。

例如,平面文件或DB,您可以添加STOP-SUSPEND_EXECUTION命令。 当脚本读取该行或行时,它将暂停正常执行,但会继续定期检查资源。 此后,如果读取了RESUME命令,则由于尚未离开迭代循环,因此从中断处继续执行。

现在,您可以通过CLI或其他界面将命令添加到队列中,应用程序将做出相应的响应。

您甚至可能会幻想,添加时间戳以延迟命令执行。

PS:如果您要执行群发邮件等任务,也许您会考虑将这些脚本移至命令行界面。 我仅基于您对“关闭浏览器”的评论来提及这一点。


可以使用一些工作,但是可以解决问题。 run()将回调函数$job作为参数。 该函数表示您正在执行的任何批处理作业(大量邮件等)的单个迭代,并将$data为数据数组。 每次迭代时,都会$job提供$data数组的下一个元素作为一组参数。

$data = array(
    array('name' => 'bob', 'email' => 'bob@site.com'),
    array('name' => 'jim', 'email' => 'jim@site.com'),
    array('name' => 'ann', 'email' => 'ann@site.com'),
);

$job = function($name, $email){
    // do something with $name
    // and $email
};

$batch->run($job, $data);

您需要一些表('la MySQL Workbench):

CREATE SCHEMA IF NOT EXISTS `batchtest` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE `batchtest` ;

CREATE  TABLE IF NOT EXISTS `batchtest`.`job` (
  `id` CHAR(24) NOT NULL ,
  `alias` VARCHAR(255) NOT NULL ,
  `status` INT NOT NULL DEFAULT 0 ,
  `timestamp` TIMESTAMP NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS `batchtest`.`queue` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `job_id` CHAR(24) NOT NULL ,
  `action` VARCHAR(255) NOT NULL ,
  `params` TEXT NULL ,
  `timestamp` TIMESTAMP NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

每当您要暂停/恢复/中止作业时,请使用job_idactionpauseresumeabort )向queue列表添加一行,然后该作业就会响应。 作业将自动从queue列表中删除完成的命令。

这就是要旨。

class BatchJob{

    const STATUS_STARTING   = 0;
    const STATUS_RUNNING    = 1; 
    const STATUS_PAUSED     = 2; 
    const STATUS_ABORTED    = 4; 
    const STATUS_COMPLETED  = 5; 

    protected $_id          = null;
    protected $_alias       = null;
    protected $_pdo         = null;
    protected $_pauseSleep  = null;
    protected $_status      = self::STATUS_STARTING;
    protected $_jobTable    = 'job';
    protected $_queueTable  = 'queue';

    public function __construct($pdo, $alias){
        $this->_pdo     = $pdo;
        $this->_alias   = $alias;
        $this->_id       = vsprintf('%04x%04x%04x%04x%04x%04x', array(
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
        ));
        $this->output("Initializing job");
        $this->_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $statement = $this->_pdo->prepare("INSERT INTO {$this->_jobTable} (id, alias, status) VALUES (:id, :alias, :status)");
        $statement->execute(array(
            ':id'       => $this->_id,
            ':alias'    => $this->_alias,
            ':status'   => $this->_status,
        ));
    }

    public function run($job, Array $data, $pauseSleep = 10){
        $this->_pauseSleep  = $pauseSleep;
        $iteration          = 0;
        $this->updateStatus(self::STATUS_RUNNING);

        while($this->_status != self::STATUS_ABORTED
            &&$this->_status != self::STATUS_COMPLETED){

            $statement = $this->_pdo->prepare("SELECT id, action, params FROM {$this->_queueTable} WHERE job_id = :job_id");
            $statement->execute(array(
                ':job_id'       => $this->_id,
            ));

            foreach($statement->fetchAll() as $command){
                switch($command['action']){
                    case 'resume':
                        $this->updateStatus(self::STATUS_RUNNING);
                        break;
                    case 'pause':
                        $this->updateStatus(self::STATUS_PAUSED);
                        break;
                    case 'abort':
                        $this->updateStatus(self::STATUS_ABORTED, true, false);
                        exit;
                        break;
                }
                $statement = $this->_pdo->prepare("DELETE FROM {$this->_queueTable} WHERE id = :id");
                $statement->execute(array(
                    ':id'   => $command['id'],
                ));
            }

            if($this->_status == self::STATUS_PAUSED){
                sleep($this->_pauseSleep);
                continue;
            }

            call_user_func_array($job, (Array) current($data));

            if(!next($data)){
                $this->updateStatus(self::STATUS_COMPLETED, true, false);
            }

        }
    }

    protected function output($string){
        echo ">>> [{$this->_alias}:{$this->_id}] [" . date('Y-m-d H:i:s') . "] {$string}" . PHP_EOL;
    }

    protected function updateStatus($status = null, $updateDatabase = true, $updateOutput = true){
        if(!is_null($status)){
            $this->_status = $status;
        }

        if($updateDatabase){
            $statement = $this->_pdo->prepare("UPDATE {$this->_jobTable} SET status = :status WHERE id = :id");
            $statement->execute(array(
                ':id'       => $this->_id,
                ':status'   => $this->_status,
            ));
        }
        if($updateOutput){
            $reflection = new ReflectionClass(__CLASS__);
            $statusCodes = array_flip($reflection->getConstants());
            $this->output("Job status change [{$statusCodes[$this->_status]}]");
        }
    }

    public function __destruct(){
        $this->updateStatus();
    }

}

如果可以修改脚本,则可以在脚本的主循环中插入这样的行(最好在mail()行之前):

if (connection_aborted ())
    exit ();

如果关闭浏览器窗口,这将停止PHP脚本。 尽管这是默认行为,但是php经常无法立即停止脚本。

您可以在不了解脚本内部很多工作的情况下执行此操作,它比杀死Apache更好。

编辑您的php.ini以在禁用功能中设置邮件。 则php将无法使用邮件功能。

disable_functions = mail

http://www.php.net/manual/en/ini.core.php#ini.disable-functions

httpd这将停止所有Apache。

通常,您将杀死Web服务器。 如果您运行cgi exe,可以将其杀死。

您是否在问如何关闭发狂的php脚本? 如果是这样,您可以随时重新启动apache。 如果我误解了您的问题,我向您致歉。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM