php - instalar - ejecutar crontab manualmente
Cómo evitar la ejecución del trabajo cron, si ya se está ejecutando (9)
El bloqueo consultivo se hace para este propósito exacto.
Puede realizar el bloqueo de advertencia con flock()
. Simplemente aplique la función a un archivo de bloqueo abierto previamente para determinar si otro script tiene un bloqueo en él.
$f = fopen(''lock'', ''w'') or die (''Cannot create lock file'');
if (flock($f, LOCK_EX | LOCK_NB)) {
// yay
}
En este caso, estoy agregando LOCK_NB
para evitar que la siguiente secuencia de comandos espere hasta que la primera haya terminado. Ya que estás usando cron siempre habrá una siguiente secuencia de comandos.
Si el script actual termina prematuramente, cualquier bloqueo de archivos se liberará por el sistema operativo.
Tengo un script php, y ejecuto este script a través de cron cada 10 minutos en CentOS.
El problema es que si el trabajo cron toma más de 10 minutos, entonces se iniciará otra instancia del mismo trabajo cron.
Probé un truco, que es:
- Creó un archivo de bloqueo con código php (igual que los archivos pid) cuando se inició el trabajo cron.
- Se eliminó el archivo de bloqueo con código php cuando finalizó el trabajo.
- Y cuando cualquier nuevo trabajo cron inició la ejecución del script, verifiqué si existe un archivo de bloqueo y, de ser así, aborté el script.
Pero puede haber un problema que, cuando la secuencia de comandos no elimina o elimina el archivo de bloqueo por algún motivo. El cron nunca volverá a empezar.
¿Hay alguna manera de que pueda detener la ejecución de un trabajo cron nuevamente si ya se está ejecutando, con comandos de Linux o similar a este?
Estaba ejecutando un script de trabajo cron php que trataba específicamente con el envío de mensajes de texto utilizando una API existente. En mi casilla local, el trabajo cron funcionaba bien, pero en la casilla de mi cliente enviaba mensajes dobles. Aunque esto no tiene sentido para mí, verifiqué los permisos de la carpeta responsable del envío de mensajes y el permiso se configuró como root. Una vez que configuré al propietario como www-data (Ubuntu), comenzó a comportarse normalmente.
Este podría ser el problema para usted, pero si se trata de un simple script cron, volvería a verificar los permisos.
Este es un problema muy común con una solución muy simple: cronjoblock
un cronjoblock
simple de shellscript de 8 líneas aplica el bloqueo usando el rebaño:
https://gist.github.com/coderofsalvation/1102e56d3d4dcbb1e36f
por cierto
cronjoblock
también invierte el correo electrónico no deseado de Cron: comportamiento solo de salida si las cosas salen mal. Esto es útil con respecto a la variable MAILTO de Cron''s. La salida stdout / stderr se suprimirá (por lo tanto, cron no enviará correos) a menos que el proceso dado tenga un código de salida> 0
Otra alternativa:
<?php
/**
* Lock manager to ensure our cron doesn''t run twice at the same time.
*
* Inspired by the lock mechanism in Mage_Index_Model_Process
*
* Usage:
*
* $lock = Mage::getModel(''stcore/cron_lock'');
*
* if (!$lock->isLocked()) {
* $lock->lock();
* // Do your stuff
* $lock->unlock();
* }
*/
class ST_Core_Model_Cron_Lock extends Varien_Object
{
/**
* Process lock properties
*/
protected $_isLocked = null;
protected $_lockFile = null;
/**
* Get lock file resource
*
* @return resource
*/
protected function _getLockFile()
{
if ($this->_lockFile === null) {
$varDir = Mage::getConfig()->getVarDir(''locks'');
$file = $varDir . DS . ''stcore_cron.lock'';
if (is_file($file)) {
$this->_lockFile = fopen($file, ''w'');
} else {
$this->_lockFile = fopen($file, ''x'');
}
fwrite($this->_lockFile, date(''r''));
}
return $this->_lockFile;
}
/**
* Lock process without blocking.
* This method allow protect multiple process runing and fast lock validation.
*
* @return Mage_Index_Model_Process
*/
public function lock()
{
$this->_isLocked = true;
flock($this->_getLockFile(), LOCK_EX | LOCK_NB);
return $this;
}
/**
* Lock and block process.
* If new instance of the process will try validate locking state
* script will wait until process will be unlocked
*
* @return Mage_Index_Model_Process
*/
public function lockAndBlock()
{
$this->_isLocked = true;
flock($this->_getLockFile(), LOCK_EX);
return $this;
}
/**
* Unlock process
*
* @return Mage_Index_Model_Process
*/
public function unlock()
{
$this->_isLocked = false;
flock($this->_getLockFile(), LOCK_UN);
return $this;
}
/**
* Check if process is locked
*
* @return bool
*/
public function isLocked()
{
if ($this->_isLocked !== null) {
return $this->_isLocked;
} else {
$fp = $this->_getLockFile();
if (flock($fp, LOCK_EX | LOCK_NB)) {
flock($fp, LOCK_UN);
return false;
}
return true;
}
}
/**
* Close file resource if it was opened
*/
public function __destruct()
{
if ($this->_lockFile) {
fclose($this->_lockFile);
}
}
}
Tal vez es mejor no escribir código si puedes configurarlo:
https://serverfault.com/questions/82857/prevent-duplicate-cron-jobs-running
Yo uso esto ::
<?php
// Create a PID file
if (is_file (dirname ($_SERVER[''SCRIPT_NAME'']) . "/.processing")) { die (); }
file_put_contents (dirname ($_SERVER[''SCRIPT_NAME'']) . "/.processing", "processing");
// SCRIPT CONTENTS GOES HERE //
@unlink (dirname ($_SERVER[''SCRIPT_NAME'']) . "/.processing");
?>
flock no funcionará en PHP 5.3.3 ya que se eliminó el desbloqueo automático cuando se cerró el manejador de recursos del archivo. Desbloquear ahora siempre tiene que hacerse manualmente.
flock()
funcionó muy bien para mí: tengo un trabajo cron con solicitudes de base de datos programadas cada 5 minutos, por lo que es crucial no tener varias que se ejecuten al mismo tiempo. Esto es lo que hice:
$filehandle = fopen("lock.txt", "c+");
if (flock($filehandle, LOCK_EX | LOCK_NB)) {
// code here to start the cron job
flock($filehandle, LOCK_UN); // don''t forget to release the lock
} else {
// throw an exception here to stop the next cron job
}
fclose($filehandle);
En caso de que no desee finalizar el siguiente trabajo cron programado, simplemente deténgalo hasta que finalice el trabajo en ejecución, luego omita el LOCK_NB
:
if (flock($filehandle, LOCK_EX))
#!/bin/bash
ps -ef | grep -v grep | grep capture_12hz_sampling_track.php
if [ $? -eq 1 ];
then
nohup /usr/local/bin/php /opt/Apache/htdocs/cmsmusic_v2/script/Mp3DownloadProcessMp4/capture_12hz_sampling_track.php &
else
echo "Already running"
fi