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

问题描述:

我有一个PHP应用程序(使用LAMP堆栈),发送数千个应用程序。我很想停止强制发送电子邮件。显然,我无法通过关闭浏览器来阻止senidng。如何停止PHP脚本?阻止电子邮件被发送?

我应该杀死进程,还是有其他方法可以这样做?我应该杀死哪个进程?可能有多个..?

PS:当然,应用程序的设计很糟糕......但这不是问题。

+0

如果您可以修改的源代码,添加一个'file_exists()'检查,将“取消”的文件,如果文件存在退出应用程序,可能是最彻底的方法。要停止该过程,只需在定义的目录中创建该文件即可。 (当然还有其他几种实现这种触发器的方法。) – 2011-03-30 15:46:59

+0

如何发送电子邮件?有几种方法可以在PHP中执行此操作。 – mpdonadio 2011-03-30 15:49:17

+0

@MOD> mail()函数是发送电子邮件的方式。 – Cedric 2011-03-30 16:35:42

如果是你自己的(自写的)应用程序,也许你应该添加一些功能,让你暂停或暂停执行。

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

例如,平面文件或DB,您可以添加一个STOP-SUSPEND_EXECUTION命令。当脚本读取该行或行时,它会暂停正常执行,但会继续定期检查资源。之后,如果读取RESUME命令,则执行将从其停止的位置恢复,因为它尚未离开迭代循环。

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

你甚至可以看中它,添加时间戳来推迟命令执行。 PS:如果你正在执行群发邮件等任务,也许你会考虑将这些脚本移动到命令行界面。我只根据你对“关闭浏览器”的评论提到这一点。


可以使用一些工作,但它有窍门。 run()以回调函数$job作为参数。该函数表示您正在执行的任何批处理作业(群发邮件等)以及作为数据数组的单个迭代。在每次迭代中,$job作为一组参数被赋予$data数组的下一个元素。

$data = array(
    array('name' => 'bob', 'email' => '[email protected]'), 
    array('name' => 'jim', 'email' => '[email protected]'), 
    array('name' => 'ann', 'email' => '[email protected]'), 
); 

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

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

你需要一些表(一个“拉MySQL工作台):

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; 

每当你要暂停/恢复/中止任务,增加一行到queue表与job_idactionpause,resumeabort)并且作业会作出回应。作业将自动从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(); 
    } 

} 

httpd - 这将停止所有的Apache。

通常你会杀死Web服务器。如果你运行cgi exe,你可以杀死它。

你问的如何关闭一个疯狂的php脚本?如果是这样,你总是可以重新启动Apache。如果我误解了你的问题,我提前道歉。

如果你可以修改脚本,你可以插入这样一行的脚本(最好是前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