我有一个php应用程序(使用LAMP堆栈),可以发送数千个应用程序。我很想通过强制发送电子邮件来阻止。我显然无法通过关闭浏览器来阻止senidng。
我应该杀死进程,还是有其他方法可以执行此操作?我应该杀死什么过程?可能有不止一个......?
PS:当然,应用程序的设计很糟糕......但这不是问题。答案 0 :(得分:2)
如果它是您自己的(自编)应用程序,也许您应该添加一些允许您暂停或暂停执行的功能。
一个例子是每次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);
你需要一些表格('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;
每当您想要暂停/恢复/中止作业时,请使用queue
和job_id
(action
,pause
向resume
表添加一行},或abort
),工作将作出回应。该作业将自动从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();
}
}
答案 1 :(得分:1)
如果您可以修改脚本,可以在脚本的主循环中插入这样的一行(最好在mail()
行之前):
if (connection_aborted ())
exit ();
如果您关闭浏览器窗口,这将停止PHP脚本。虽然这是默认行为,但PHP通常无法立即停止脚本。
你可以在不了解脚本内部工作的情况下做到这一点,它比杀死Apache更好。
答案 2 :(得分:0)
httpd
- 这将阻止所有Apache。
答案 3 :(得分:0)
通常,您会终止Web服务器。如果你运行cgi exe,你可以杀死它。
答案 4 :(得分:0)
你问的是如何关闭一个疯狂的PHP脚本?如果是这样,你总是可以重启apache。如果我误解了你的问题,我会事先道歉。
答案 5 :(得分:0)
编辑php.ini以在disabled-functions中设置邮件。那么php将无法使用邮件功能。
disable_functions = mail
http://www.php.net/manual/en/ini.core.php#ini.disable-functions