Cập nhật
Tôi đã giải quyết vấn đề và đăng một câu trả lời. Tuy nhiên, giải pháp của tôi không lý tưởng 100%. Tôi chỉ muốn loại bỏ symlink
khỏi cache
với clearstatcache(true, $target)
hoặc clearstatcache(true, $link)
nhưng điều đó không làm việc.
Tôi cũng muốn ngăn chặn bộ đệm của các liên kết tượng trưng ở vị trí đầu tiên hoặc loại bỏ liên kết tượng trưng khỏi bộ đệm ngay sau khi tạo nó. Thật không may, tôi đã không có may mắn với điều đó. Vì một số lý do clearstatcache(true)
sau khi tạo symlink không hoạt động, nó vẫn được lưu trữ.
Tôi sẽ vui vẻ trao tiền thưởng cho bất cứ ai có thể cải thiện câu trả lời của tôi và giải quyết những vấn đề đó.
Biên tập
Tôi đã cố gắng tối ưu hóa mã của mình bằng cách tạo tệp mỗi clearstatcache
lần chạy, do đó tôi chỉ cần xóa bộ đệm một lần cho mỗi liên kết tượng trưng. Vì một số lý do, điều này không hoạt động. clearstatcache
cần được gọi mỗi khi a symlink
bao gồm trong đường dẫn, nhưng tại sao? Phải có một cách để tối ưu hóa giải pháp tôi có.
Tôi đang sử dụng PHP 7.3.5
với nginx/1.16.0
. Đôi khi file_get_contents
trả về giá trị sai khi sử dụng a symlink
. Vấn đề là sau khi xóa và tạo lại một liên kết tượng trưng, giá trị cũ của nó vẫn nằm trong bộ đệm. Đôi khi giá trị đúng được trả về, đôi khi giá trị cũ. Nó xuất hiện ngẫu nhiên.
Tôi đã cố gắng xóa bộ nhớ cache hoặc ngăn bộ đệm với:
function symlink1($target, $link)
{
realpath_cache_size(0);
symlink($target, $link);
//clearstatcache(true);
}
Tôi thực sự không muốn tắt bộ nhớ đệm nhưng tôi vẫn cần độ chính xác 100% với file_get_contents.
Biên tập
Tôi không thể đăng mã nguồn của mình, vì nó quá dài và phức tạp, vì vậy tôi đã tạo ra một ví dụ tối thiểu, có thể lặp lại (index.php) để tạo lại vấn đề:
<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>
Nó dường như rất có thể là một vấn đề với Nginx
cấu hình. Không có những dòng này có thể gây ra vấn đề:
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
Đây là Nginx
cấu hình của tôi (bạn có thể thấy tôi đã bao gồm các dòng trên):
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;
}
Hiện tại tôi có ví dụ trên trực tiếp tại https://www.websemantica.co.uk .
Hãy thử thêm một vài giá trị trong biểu mẫu. Nó sẽ hiển thị Success!
màu xanh mỗi lần. Đôi khi được hiển thị Failure!
màu đỏ. Có thể mất khá nhiều lần làm mới trang để thay đổi từ Success!
sang Failure!
hoặc ngược lại. Cuối cùng, nó sẽ hiển thị Success!
mọi lúc, do đó phải có một số loại vấn đề bộ đệm.
realpath
với file_get_conents
và không may mắn. Nó vẫn đôi khi tải từ bộ đệm.
realpath
, mà là một cái gì đó giống nhưclearstatcache(true); file_get_conents(realpath($fileName));
realpath
trang chức năng . Có lẽ nó có thể giúp bạn.