getmypid

(PHP 4, PHP 5, PHP 7, PHP 8)

getmypid获取 PHP 的进程 ID

说明

getmypid(): int|false

获取当前 PHP 进程 ID。

参数

此函数没有参数。

返回值

返回当前 PHP 进程 ID,如果发生错误则返回 false

注释

警告

进程 ID 不是唯一的,因此它们是弱熵源。我们建议不要在依赖安全的上下文中依赖 pid。

参见

添加注释

用户贡献的注释 14 个注释

Radu Cristescu
11 年前
Kevin Trass 在注释中提到的锁文件机制是错误的,因为它容易受到竞争条件的影响。

对于锁,您需要一种原子方法来验证锁文件是否存在,如果不存在则创建它。在 `file_exists` 和 `file_put_contents` 之间,另一个进程可能比我们更快地写入锁。

我所知道的唯一匹配上述要求的文件系统操作是 `symlink()`。

因此,如果您需要锁文件机制,请使用以下代码。这在没有 `/proc` 的系统上不起作用(因此,Windows、BSD、OS X 以及可能的其他系统无法使用),但可以调整以解决此缺陷(例如,通过像我的脚本中一样链接到您的 pid 文件,然后通过符号链接像 Kevin 的解决方案中那样操作)。

#!/usr/bin/php
<?php

define
('LOCK_FILE', "/var/run/" . basename($argv[0], ".php") . ".lock");

if (!
tryLock())
die(
"Already running.\n");

# 退出时删除锁(Control+C 不算作“退出”?)
register_shutdown_function('unlink', LOCK_FILE);

# 您的脚本的其余部分位于此处....
echo "Hello world!\n";
sleep(30);

exit(
0);

function
tryLock()
{
# 如果锁文件存在,检查是否已过期。如果存在且没有过期,则返回 TRUE
# 否则,创建锁文件并返回 FALSE。

if (@symlink("/proc/" . getmypid(), LOCK_FILE) !== FALSE) # 'symlink' 前面的 @ 用于抑制如果 LOCK_FILE 存在时收到的 NOTICE
return true;

# 链接已存在
# 检查它是否已过期
if (is_link(LOCK_FILE) && !is_dir(LOCK_FILE))
{
unlink(LOCK_FILE);
# 尝试再次锁定
return tryLock();
}

return
false;
}
?>
Robert Mays Jr
13 年前
以上所有示例都要求您启用 shell 命令执行 - 此示例仅使用 PHP 函数,应在任何系统上运行(posix 默认情况下包含)-

关键是 `posix_getsid`,如果进程不存在,它将返回 FALSE。

<?php
$lockfile
= sys_get_temp_dir() . '/myScript.lock';
$pid = file_get_contents($lockfile);
if (
posix_getsid($pid) === false) {
print
"process has died! restarting...\n";
file_put_contents($lockfile, getmypid()); // 创建锁文件
} else {
print
"PID is still alive! can not run twice!\n";
exit;
}
?>

:-) 如果您需要确保 cron 作业或 shell 脚本在再次启动之前已结束,这非常完美。

这适用于所有用户 - 如果 cron 作业以“root”身份启动,您的“web 用户”可以查看进程是否还处于活动状态(这对系统状态页面很有用)
brospam at gmail dot com
10 年前
我的锁文件系统

<?php
function isLocked(){
if(
file_exists(LOCK_FILE)) {
$lockingPID = trim(file_get_contents(LOCK_FILE));
$test=trim(`ps -p $lockingPID -o pid=`);
if(!empty(
$test)) return true;
echo
"Removing stale lock file.\n";
unlink(LOCK_FILE);
}
file_put_contents(LOCK_FILE, getmypid()."\n");
return
false;
}
?>
Kevin Traas (ktraas- at -gmail dot com)
14 年前
想要为命令行脚本创建锁文件机制吗?

尽情享受!

#!/usr/bin/php
<?php

define
( 'LOCK_FILE', "/var/run/".basename( $argv[0], ".php" ).".lock" );
if(
isLocked() ) die( "Already running.\n" );

# The rest of your script goes here....
echo "Hello world!\n";
sleep(30);

unlink( LOCK_FILE );
exit(
0);

function
isLocked()
{
# If lock file exists, check if stale. If exists and is not stale, return TRUE
# Else, create lock file and return FALSE.

if( file_exists( LOCK_FILE ) )
{
# check if it's stale
$lockingPID = trim( file_get_contents( LOCK_FILE ) );

# Get all active PIDs.
$pids = explode( "\n", trim( `ps -e | awk '{print $1}'` ) );

# If PID is still active, return true
if( in_array( $lockingPID, $pids ) ) return true;

# Lock-file is stale, so kill it. Then move on to re-creating it.
echo "Removing stale lock file.\n";
unlink( LOCK_FILE );
}

file_put_contents( LOCK_FILE, getmypid() . "\n" );
return
false;

}
?>
brooke at jump dot net
20 年前
此代码的一个好用途是决定并发安全的临时文件或目录名。您可以确保同一台服务器上的两个进程不会拥有相同的 PID,因此这足以避免冲突。例如

<?php
$tmpfile
= "/tmp/foo_".getmypid();
// 使用 $tmpfile...
// 使用 $tmpfile...
// 使用 $tmpfile...
unlink ($tmpfile);
?>

如果您在网络上共享 /tmp(这很奇怪……),那么您当然可以将 PHP 服务器的 IP 地址混合进去。
wouter99999 at gmail dot com
13 年前
在 Windows 上,ps 不可使用。相反,要查看正在运行的进程列表,您可以使用 exec('tasklist'); 要终止进程,您可以使用 exec('taskkill'); 输入 taskkill /? 以获取更多信息。
eight_hf at live dot fr
12 年前
在 Linux 上,您可以通过验证 PID 是否存在于 /proc 目录中来检查进程是否仍在运行

<?php
if(file_exists('/proc/'.$pid))
{
echo
'The process is still running.';
}
?>
kroczu at interia dot pl
18 年前
<?php
/*

mixed getpidinfo(mixed pid [, string system_ps_command_options])

此函数从系统 ps 命令获取 PID 信息并将其返回到有用的关联数组中,
或在 PID 不存在时返回 false 并触发警告

$pidifo=getpidinfo(12345);

print_r($pidifo);

Array
(
[USER] => user
[PID] => 12345
[%CPU] => 0.0
[%MEM] => 0.0
[VSZ] => 1720
[RSS] => 8
[TT] => ??
[STAT] => Is
[STARTED] => 6:00PM
[TIME] => 0:00.01
[COMMAND] => php someproces.php > logfile
)

*/

//////////////////////////////////////////////

function getpidinfo($pid, $ps_opt="aux"){

$ps=shell_exec("ps ".$ps_opt."p ".$pid);
$ps=explode("\n", $ps);

if(
count($ps)<2){
trigger_error("PID ".$pid." doesn't exists", E_USER_WARNING);
return
false;
}

foreach(
$ps as $key=>$val){
$ps[$key]=explode(" ", ereg_replace(" +", " ", trim($ps[$key])));
}

foreach(
$ps[0] as $key=>$val){
$pidinfo[$val] = $ps[1][$key];
unset(
$ps[1][$key]);
}

if(
is_array($ps[1])){
$pidinfo[$val].=" ".implode(" ", $ps[1]);
}
return
$pidinfo;
}

?>
Erickson Reyes ercbluemonday at yahoo dot com
14 年前
我们公司也面临过这个挑战,需要防止 cron 作业中的 php 脚本相互重叠。

我们做了以下解决方案

<?php
// 初始化变量
$found = 0;
$file = basename(__FILE__);
$commands = array();

// 获取正在运行的进程。
exec("ps w", $commands);

// 如果找到进程
if (count($commands) > 0) {

foreach (
$commands as $command) {
if (
strpos($command, $file) === false) {
// 不做任何事
}
else {
// 让我们统计一下文件出现的次数。
$found++;
}
}
}

// 如果找到文件实例超过一次。
if ($found > 1) {
echo
"Another process is running.\n";
die();
}

/**
*
* 这里执行常规进程...
*
*/
?>
pdc at example dot com
12 年前
以下是如何在 posix 系统上使用 exec 来快速完成进程计数。

我想知道有多少进程正在运行命令 'update.php'

ps aux|grep "[u]pdate.php"|wc -l

(使用 [u]pdate.php 而不是 update.php 的技巧可以确保 grep 命令本身不会被匹配)。请确保在命令中使用引号,否则它将无法工作。

所以,代码如下

<?php
function countProcesses($scriptName)
{
// ps aux|grep "[u]pdate.php"|wc -l
$first = substr($scriptName, 0, 1);
$rest = substr($scriptName, 1);

$name = '"['.$first.']'.$rest.'"';
$cmd = "ps aux | grep $name | wc -l";

$result = exec($cmd);

return
$result;
}
?>
martijn at nowhere dot com
8 年前
在 Windows 上,您可以使用以下单行语句获取 PID 列表:<?php $pids = array_column(array_map('str_getcsv', explode("\n",trim(`tasklist /FO csv /NH`))), 1); ?>.
Pure-PHP
19 年前
您也可以使用此函数来避免您的应用程序出现多个实例。

您也可以使用此类。
http://www.pure-php.de/node/20

用法

<?php

inlude
("ProcessHandler.class.php");

if(
ProcessHandler::isActive()){
die(
"Already running!\n";);
}else{
ProcessHandler::activate();
//运行我的应用程序
}

?>
gabe at fijiwebdesign dot com
14 年前
基于 james at voodoo dot co dot uk 所述内容,但针对 CLI 脚本进行了修改(即:没有 $_SERVER)。

<?php

/**
* 检查当前进程(按文件名)
* @param $file[可选] 文件名
* @return 布尔值
*/
function processExists($file = false) {

$exists = false;
$file = $file ? $file : __FILE__;

// 检查文件是否在进程列表中
exec("ps -C $file -o pid=", $pids);
if (
count($pids) > 1) {
$exists = true;
}
return
$exists;
}

?>
james at voodoo dot co dot uk
14 年前
“ps” 命令有一个选项可以使针对特定进程的过滤更加有效。使用它可以更简洁地完成查找匹配进程的工作

<?php
/*
返回运行特定命令的进程的 PID 数组
例如:
returnPids('myprocess.php');
*/
function returnPids($command) {
exec("ps -C $command -o pid=",$pids);
foreach (
$pids as $key=>$value) $pids[$key]=trim($value);
return
$pids;
}

/*
返回与我类似的进程的 PID 数组,即正在运行我的程序
*/
function returnMyPids() {
return
returnPids(basename($_SERVER["SCRIPT_NAME"]));
}
?>

例如,如果我已经在运行,就退出

if (count(returnMyPids())>1) exit;
To Top