최신 정보
문제를 해결하고 답변을 게시했습니다. 그러나 내 솔루션은 100 % 이상적이지 않습니다. 나는 차라리만을 제거 할 symlink으로부터 cache와 clearstatcache(true, $target)또는 clearstatcache(true, $link)그러나 그것은 작동하지 않습니다.
또한 심볼릭 링크를 처음에 캐싱하는 것을 막거나 심볼을 생성 한 직후 캐시에서 심볼릭 링크를 제거합니다. 불행히도, 나는 그것에 운이 없었습니다. 어떤 이유로 clearstatcache(true)symlink를 작성한 후에도 작동하지 않더라도 여전히 캐시됩니다.
내 답변을 개선 하고 해당 문제를 해결할 수있는 사람에게 현상금을 기꺼이 수여합니다 .
편집하다
매번 clearstatcache실행될 때마다 파일을 생성하여 코드를 최적화하려고 시도 했기 때문에 각 심볼릭 링크마다 캐시를 한 번만 지우면됩니다. 어떤 이유로, 이것은 작동하지 않습니다. 경로 clearstatcache에 포함될 때마다 호출해야 symlink하지만 왜 그럴까요? 내가 가진 솔루션을 최적화하는 방법이 있어야합니다.
PHP 7.3.5와 함께 사용 하고 nginx/1.16.0있습니다. 를 file_get_contents사용할 때 때때로 잘못된 값을 반환합니다 symlink. 문제는 심볼릭 링크를 삭제하고 다시 만든 후에 이전 값이 캐시에 남아 있다는 것입니다. 때로는 올바른 값, 때로는 이전 값이 반환됩니다. 무작위로 나타납니다.
캐시를 지우거나 캐싱을 방지하려고했습니다.
function symlink1($target, $link)
{
realpath_cache_size(0);
symlink($target, $link);
//clearstatcache(true);
}
캐싱을 비활성화하고 싶지 않지만 file_get_contents와 함께 여전히 100 % 정확도가 필요합니다.
편집하다
너무 길고 복잡하여 소스 코드를 게시 할 수 없으므로 문제를 재현하는 최소한의 재현 가능한 예제 (index.php)를 만들었습니다.
<h1>Symlink Problem</h1>
<?php
$dir = getcwd();
if (isset($_POST['clear-all']))
{
$nos = array_values(array_diff(scandir($dir.'/nos'), array('..', '.')));
foreach ($nos as $no)
{
unlink($dir.'/nos/'.$no.'/id.txt');
rmdir($dir.'/nos/'.$no);
}
foreach (array_values(array_diff(scandir($dir.'/ids'), array('..', '.'))) as $id)
unlink($dir.'/ids/'.$id);
}
if (!is_dir($dir.'/nos'))
mkdir($dir.'/nos');
if (!is_dir($dir.'/ids'))
mkdir($dir.'/ids');
if (isset($_POST['submit']) && !empty($_POST['id']) && ctype_digit($_POST['insert-after']) && ctype_alnum($_POST['id']))
{
$nos = array_values(array_diff(scandir($dir.'/nos'), array('..', '.')));
$total = count($nos);
if ($total <= 100)
{
for ($i = $total; $i >= $_POST['insert-after']; $i--)
{
$id = file_get_contents($dir.'/nos/'.$i.'/id.txt');
unlink($dir.'/ids/'.$id);
symlink($dir.'/nos/'.($i + 1), $dir.'/ids/'.$id);
rename($dir.'/nos/'.$i, $dir.'/nos/'.($i + 1));
}
echo '<br>';
mkdir($dir.'/nos/'.$_POST['insert-after']);
file_put_contents($dir.'/nos/'.$_POST['insert-after'].'/id.txt', $_POST['id']);
symlink($dir.'/nos/'.$_POST['insert-after'], $dir.'/ids/'.$_POST['id']);
}
}
$nos = array_values(array_diff(scandir($dir.'/nos'), array('..', '.')));
$total = count($nos) + 1;
echo '<h2>Ids from nos directory</h2>';
foreach ($nos as $no)
{
echo ($no + 1).':'.file_get_contents("$dir/nos/$no/id.txt").'<br>';
}
echo '<h2>Ids from using symlinks</h2>';
$ids = array_values(array_diff(scandir($dir.'/ids'), array('..', '.')));
if (count($ids) > 0)
{
$success = true;
foreach ($ids as $id)
{
$id1 = file_get_contents("$dir/ids/$id/id.txt");
echo $id.':'.$id1.'<br>';
if ($id !== $id1)
$success = false;
}
if ($success)
echo '<b><font color="blue">Success!</font></b><br>';
else
echo '<b><font color="red">Failure!</font></b><br>';
}
?>
<br>
<h2>Insert ID after</h2>
<form method="post" action="/">
<select name="insert-after">
<?php
for ($i = 0; $i < $total; $i++)
echo '<option value="'.$i.'">'.$i.'</option>';
?>
</select>
<input type="text" placeholder="ID" name="id"><br>
<input type="submit" name="submit" value="Insert"><br>
</form>
<h2>Clear all</h2>
<form method="post" action="/">
<input type="submit" name="clear-all" value="Clear All"><br>
</form>
<script>
if (window.history.replaceState)
{
window.history.replaceState( null, null, window.location.href );
}
</script>
Nginx구성에 문제가있는 것 같습니다 . 이 줄이 없으면 문제가 발생할 수 있습니다.
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
여기 내 Nginx구성이 있습니다 (위의 줄을 포함시킨 것을 볼 수 있습니다).
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.websemantica.co.uk;
root "/path/to/site/root";
index index.php;
location / {
try_files $uri $uri/ $uri.php$is_args$query_string;
}
location ~* \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $realpath_root$fastcgi_path_info;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param HTTPS $https;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_index index.php;
fastcgi_read_timeout 3000;
}
if ($request_uri ~ (?i)^/([^?]*)\.php($|\?)) {
return 301 /$1$is_args$args;
}
rewrite ^/index$ / permanent;
rewrite ^/(.*)/$ /$1 permanent;
}
현재 위의 예제는 https://www.websemantica.co.uk에 있습니다.
양식에 몇 가지 값을 추가하십시오. Success!매번 파란색으로 표시되어야합니다 . 때로는 Failure!빨간색 으로 표시 됩니다. 그것은에서 변경 꽤 많은 페이지 새로 고침이 걸릴 수 Success!로 Failure!또는 그 반대의 경우도 마찬가지입니다. 결국에는 Success!매번 표시 되므로 일종의 캐싱 문제가 있어야합니다.
realpath와 함께 file_get_conents하고 행운. 여전히 캐시에서로드되기도합니다.
realpath뿐만 아니라 다음과 같은 의미입니다clearstatcache(true); file_get_conents(realpath($fileName));
realpath함수 페이지 에서 매우 유용한 주석을 발견했습니다 . 아마 도움이 될 수 있습니다.