我有一個PHP應用程序(使用LAMP堆棧),發送數千個應用程序。我很想停止強制發送電子郵件。顯然,我無法通過關閉瀏覽器來阻止senidng。如何停止PHP腳本?阻止電子郵件被髮送?
我應該殺死進程,還是有其他方法可以這樣做?我應該殺死哪個進程?可能有多個..?
PS:當然,應用程序的設計很糟糕......但這不是問題。
我有一個PHP應用程序(使用LAMP堆棧),發送數千個應用程序。我很想停止強制發送電子郵件。顯然,我無法通過關閉瀏覽器來阻止senidng。如何停止PHP腳本?阻止電子郵件被髮送?
我應該殺死進程,還是有其他方法可以這樣做?我應該殺死哪個進程?可能有多個..?
PS:當然,應用程序的設計很糟糕......但這不是問題。
如果是你自己的(自寫的)應用程序,也許你應該添加一些功能,讓你暫停或暫停執行。
一個例子是每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_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();
}
}
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
如果您可以修改的源代碼,添加一個'file_exists()'檢查,將「取消」的文件,如果文件存在退出應用程序,可能是最徹底的方法。要停止該過程,只需在定義的目錄中創建該文件即可。 (當然還有其他幾種實現這種觸發器的方法。) – 2011-03-30 15:46:59
如何發送電子郵件?有幾種方法可以在PHP中執行此操作。 – mpdonadio 2011-03-30 15:49:17
@MOD> mail()函數是發送電子郵件的方式。 – Cedric 2011-03-30 16:35:42