Оновлення
Я вирішив проблему і опублікував відповідь. Однак моє рішення не є 100% ідеальним. Я волів би тільки прибрати symlink
з cache
з clearstatcache(true, $target)
або , clearstatcache(true, $link)
але це не працює.
Я також набагато краще запобігти кешування символьних посилань в першу чергу або видалити символьне посилання з кешу відразу після його створення. На жаль, мені не пощастило з цим. Чомусь clearstatcache(true)
після створення символьної посилання не працює, вона все одно отримує кешування.
Я із задоволенням нагороду нагороджую всіх, хто може покращити мою відповідь та вирішити ці питання.
Редагувати
Я намагався оптимізувати свій код, генеруючи файл щоразу, коли 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);
}
Я не хочу дуже відключати кешування, але мені все одно потрібна 100% точність з file_get_contents.
Редагувати
Я не можу розмістити свій вихідний код, оскільки він занадто довгий і складний, тому я створив мінімальний, відтворюваний приклад (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
сторінці функцій . Можливо, це могло б вам допомогти.