为什么这个用flock()获取的文件锁在调用exec()后没有释放?
Why is this file lock acquired with flock() not released after calling exec()?
我有这个 PHP 8.1 的最小示例:
<?php
ini_set('display_errors', 'on');
if(($fp = @fopen(__DIR__ . '/test.some', 'r+')) === false){
$fp = fopen(__DIR__ . '/test.some', 'c+');
}
flock($fp, LOCK_EX);
exec('eval `ssh-agent -s`', $output1, $resultCode1);
var_dump($output1, $resultCode1);
fclose($fp);
问题是,当我 运行 这个脚本两次时,第二个实例将阻塞在 flock() 函数调用上,据说是因为第一个没有释放文件锁。
当我 exec() 一个不同的命令而不是 eval `ssh-agent -s`
,例如 git --version
,然后一切似乎工作正常。
有人知道问题出在哪里吗?是PHP的BUG还是我对flock()的理解太差?
通常,当进程退出时,所有文件锁都会自动释放 (source)。但是,ssh-agent
被派生为后台进程,这导致它从父进程继承所有文件锁。
此行为可以通过 运行 sudo fuser -v /tmp/test.some
确认,这表明 ssh-agent
继承了锁。
USER PID ACCESS COMMAND
/tmp/test.some: testuser 19834 F.... ssh-agent
testuser 19873 F.... php8.1
按照 Pran Joseph 评论中的建议添加 flock($fp, LOCK_UN)
,确实解决了这个问题。
我有这个 PHP 8.1 的最小示例:
<?php
ini_set('display_errors', 'on');
if(($fp = @fopen(__DIR__ . '/test.some', 'r+')) === false){
$fp = fopen(__DIR__ . '/test.some', 'c+');
}
flock($fp, LOCK_EX);
exec('eval `ssh-agent -s`', $output1, $resultCode1);
var_dump($output1, $resultCode1);
fclose($fp);
问题是,当我 运行 这个脚本两次时,第二个实例将阻塞在 flock() 函数调用上,据说是因为第一个没有释放文件锁。
当我 exec() 一个不同的命令而不是 eval `ssh-agent -s`
,例如 git --version
,然后一切似乎工作正常。
有人知道问题出在哪里吗?是PHP的BUG还是我对flock()的理解太差?
通常,当进程退出时,所有文件锁都会自动释放 (source)。但是,ssh-agent
被派生为后台进程,这导致它从父进程继承所有文件锁。
此行为可以通过 运行 sudo fuser -v /tmp/test.some
确认,这表明 ssh-agent
继承了锁。
USER PID ACCESS COMMAND
/tmp/test.some: testuser 19834 F.... ssh-agent
testuser 19873 F.... php8.1
按照 Pran Joseph 评论中的建议添加 flock($fp, LOCK_UN)
,确实解决了这个问题。