Это то, о чем я долго размышлял, и решил спросить об этом.
У нас есть функция getmypid (), которая вернет текущий идентификатор процесса скриптов. Есть ли какая-то функция, такая как
checkifpidexists () в php? Я имею в виду встроенный, а не какой-то пакетный скрипт.
И есть ли способ изменить скрипты pid?
Некоторые уточнения:
Я хочу проверить, существует ли pid, если скрипт уже запущен, поэтому он не запускается снова, работа faux cron, если хотите.
Причина, по которой я хотел изменить pid, – это то, что я могу установить сценарий pid на что-то действительно высокое, например, 60000 и жесткий код, который имеет значение, поэтому этот скрипт может работать только на этом pid, так что только один экземпляр этого будет выполняться
РЕДАКТИРОВАТЬ—-
Чтобы помочь кому-либо еще в этом вопросе, я создал этот класс:
class instance { private $lock_file = ''; private $is_running = false; public function __construct($id = __FILE__) { $id = md5($id); $this->lock_file = sys_get_temp_dir() . $id; if (file_exists($this->lock_file)) { $this->is_running = true; } else { $file = fopen($this->lock_file, 'w'); fclose($file); } } public function __destruct() { if (file_exists($this->lock_file) && !$this->is_running) { unlink($this->lock_file); } } public function is_running() { return $this->is_running; } }
и вы используете его так:
$instance = new instance('abcd'); // the argument is optional as it defaults to __FILE__ if ($instance->is_running()) { echo 'file already running'; } else { echo 'file not running'; }
В linux вы бы посмотрели на / proc.
return file_exists( "/proc/$pid" );
В Windows вы можете использовать shell_exec () tasklist.exe и найти соответствующий идентификатор процесса:
$processes = explode( "\n", shell_exec( "tasklist.exe" )); foreach( $processes as $process ) { if( strpos( "Image Name", $process ) === 0 || strpos( "===", $process ) === 0 ) continue; $matches = false; preg_match( "/(.*?)\s+(\d+).*$/", $process, $matches ); $pid = $matches[ 2 ]; }
Я считаю, что вы хотите сохранить файл PID. В демонах, которые я написал, они проверяют файл конфигурации, ищут экземпляр pid-файла, вытаскивают pid из файла pid, проверяют, существует ли / proc / $ pid, а если нет, удалите pid файл.
if( file_exists("/tmp/daemon.pid")) { $pid = file_get_contents( "/tmp/daemon.pid" ); if( file_exists( "/proc/$pid" )) { error_log( "found a running instance, exiting."); exit(1); } else { error_log( "previous process exited without cleaning pidfile, removing" ); unlink( "/tmp/daemon.pid" ); } } $h = fopen("/tmp/daemon.pid", 'w'); if( $h ) fwrite( $h, getmypid() ); fclose( $h );
Идентификаторы процессов предоставляются ОС, и невозможно зарезервировать идентификатор процесса. Вы должны написать своего демона, чтобы уважать файл pid.
Лучшим способом для этого было бы использовать файл pid или lock. Просто проверьте наличие файла pid, создайте его по мере необходимости и заполните его текущим pid.
<? class pidfile { private $_file; private $_running; public function __construct($dir, $name) { $this->_file = "$dir/$name.pid"; if (file_exists($this->_file)) { $pid = trim(file_get_contents($this->_file)); if (posix_kill($pid, 0)) { $this->_running = true; } } if (! $this->_running) { $pid = getmypid(); file_put_contents($this->_file, $pid); } } public function __destruct() { if ((! $this->_running) && file_exists($this->_file)) { unlink($this->_file); } } public function is_already_running() { return $this->_running; } } ?>
И используйте его следующим образом:
<? $pidfile = new pidfile('/tmp', 'myscript'); if($pidfile->is_already_running()) { echo "Already running.\n"; exit; } else { echo "Started...\n"; } ?>
Здесь не так много ошибок, но быстрый запуск показывает, что это работает в моей системе.
Нет, вы не можете изменять какие-либо процессы pid. Он назначается ядром и является частью структур данных ядра
Для проверки наличия PID на машине Windows я использую:
function pidExists($pid) { exec('TASKLIST /NH /FO "CSV" /FI "PID eq '.$pid.'"', $outputA ); $outputB = explode( '","', $outputA[0] ); return isset($outputB[1])?true:false; }
Обратите внимание, что $ outputB [0] содержит сообщения, которые pid не может быть найден, если pid действительно не существует! Поэтому для проверки использования второго аргумента.
Как уже говорили другие, вы не можете изменить идентификатор процесса – он назначен и полностью управляется ядром ОС. Кроме того, вы не сказали, что это командная строка или веб-сервер: если это последний, вы даже не можете получить pid вашего скрипта.
На странице руководства для getmypid () содержатся некоторые примеры «оптимистической» блокировки. Я использую слово optimisitc, поскольку PHP никогда не будет приближаться к подобным веб-приложению asp.net, где у вас есть истинная потоковая среда с общими / статическими классами и, таким образом, Singleton's использовать / злоупотреблять. В основном у вас есть возможность:
Оба они полагаются на правильное завершение сценария (последним шагом будет удаление флага блокировки / db). Если сценарий сбой по какой-либо причине (или самой машине), вы можете оставить ручную процедуру для удаления, чтобы удалить флаг. Для этого нет простого решения, но можно было бы изучить один путь, чтобы затем взглянуть на дату-штамповать блокировку, при этом был бы суровым «если старше, чем X, последний прогон должен был быть разбит».
Не забывайте также, что вы можете получить доступ к командам оболочки через backticks (`), что даст вам доступ к стандартным * nix-инструментам для работы с pids.
источник: http://www.php.net/manual/en/language.operators.execution.php