최신 정보
문제를 해결하고 답변을 게시했습니다. 그러나 내 솔루션은 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
함수 페이지 에서 매우 유용한 주석을 발견했습니다 . 아마 도움이 될 수 있습니다.