ich eine CIFS-Freigabe haben von Windows Server 2012 R2 wie diesePHP file_exists gibt manchmal falsch für eine Datei auf CIFS-Freigabe
/etc auf Ubuntu 14.04.2 LTS (3.13.0-61-generic-Kernel) montiert/fstab
//10.1.2.3/Share /Share cifs credentials=/root/.smbcredentials/share_user,user=share_user,dirmode=0770,filemode=0660,uid=4000,gid=5000,forceuid,forcegid,noserverino,cache=none 0 0
Die gid=5000
zur Gruppe entspricht, die eine www-data
PHP Prozess ausgeführt wird.
Die Dateien werden ordnungsgemäß installiert, wenn ich über die als Benutzer www-data
angemeldete Konsole überprüfe - sie sind lesbar und entfernbar (die Operationen, die vom PHP-Skript verwendet werden).
Das PHP-Skript verarbeitet etwa 50-70 000 Dateien pro Tag. Die Dateien werden auf dem Host-Windows-Rechner erstellt und einige Zeit später wird das auf dem Linux-Rechner laufende PHP-Skript über eine neue Datei benachrichtigt, prüft, ob die Datei existiert (file_exists
), liest sie und löscht sie. Normalerweise funktioniert alles gut, aber manchmal (einige hundert bis 1-2 000 pro Tag) löst das PHP-Skript einen Fehler aus, dass die Datei nicht existiert. Das sollte niemals der Fall sein, da es nur über tatsächlich existierende Dateien informiert wird.
Wenn ich diese Dateien manuell als nicht vorhanden überprüfe, sind sie auf dem Ubuntu-Rechner korrekt zugänglich und haben ein Erstellungsdatum, bevor das PHP-Skript ihre Existenz überprüft hat.
Dann triggert ich das PHP-Skript manuell, um diese Datei aufzunehmen und sie wird ohne Probleme aufgenommen.
Was ich bereits versucht
Es gibt mehrere ähnliche Fragen, aber ich glaube, alle Ratschläge ausgeschöpft:
- Ich habe
clearstatcache()
vor der Kontrollefile_exists($f)
- Die Datei- und Verzeichnisberechtigungen sind in Ordnung (genau die gleiche Datei wird später korrekt aufgenommen)
- Der zur Überprüfung verwendete Pfad
file_exists($f)
ist ein absoluter Pfad ohne Sonderzeichen - die Dateipfade sind immer von Format/Share/11/222/333.zip
(mit verschiedenen Stellen) - I verwendet
noserverino
Aktien Parameter - Halterung verwendet I
cache=none
Aktien Parameter
/proc/fs/cifs/Stats/
Displays montieren als unten, aber ich weiß nicht, ob hier irgendetwas verdächtig ist. Der Anteil in Frage 2) \\10.1.2.3\Share
Resources in use
CIFS Session: 1
Share (unique mount targets): 2
SMB Request/Response Buffer: 1 Pool size: 5
SMB Small Req/Resp Buffer: 1 Pool size: 30
Operations (MIDs): 0
6 session 2 share reconnects
Total vfs operations: 133925492 maximum at one time: 11
1) \\10.1.2.3\Share_Archive
SMBs: 53824700 Oplocks breaks: 12
Reads: 699 Bytes: 42507881
Writes: 49175075 Bytes: 801182924574
Flushes: 0
Locks: 12 HardLinks: 0 Symlinks: 0
Opens: 539845 Closes: 539844 Deletes: 156848
Posix Opens: 0 Posix Mkdirs: 0
Mkdirs: 133 Rmdirs: 0
Renames: 0 T2 Renames 0
FindFirst: 21 FNext 28 FClose 0
2) \\10.1.2.3\Share
SMBs: 50466376 Oplocks breaks: 1082284
Reads: 39430299 Bytes: 2255596161939
Writes: 2602 Bytes: 42507782
Flushes: 0
Locks: 1082284 HardLinks: 0 Symlinks: 0
Opens: 2705841 Closes: 2705841 Deletes: 539832
Posix Opens: 0 Posix Mkdirs: 0
Mkdirs: 0 Rmdirs: 0
Renames: 0 T2 Renames 0
FindFirst: 227401 FNext 1422 FClose 0
Ein Muster, das ich glaube, ich sehe ist, dass der Fehler nur in Frage, wenn die Datei verarbeitet wurde angehoben wird bereits (gelesen und gelöscht) früher durch den PHP-Skript. Es gibt viele Dateien, die korrekt verarbeitet und später erneut verarbeitet wurden, aber ich habe diesen Fehler nie für eine Datei gesehen, die zum ersten Mal verarbeitet wird. Die Zeit zwischen der erneuten Verarbeitung variiert von 1 bis etwa 20 Tagen. Zur erneuten Verarbeitung wird die Datei unter dem gleichen Pfad auf dem Windows-Host mit aktualisiertem Inhalt einfach neu erstellt.
Was kann das Problem sein? Wie kann ich besser nachforschen? Wie kann ich feststellen, ob das Problem auf der PHP- oder OS-Seite liegt?
aktualisieren
ich die Software verschoben haben, dass die Dateien in ein Ubuntu VM erzeugt, dass die gleichen Aktien die gleiche Art und Weise montiert. Diese Komponente ist in Java codiert. Ich sehe keine Probleme beim Lesen/Schreiben in die Dateien.
Update - PHP Details
Der genaue PHP-Code ist:
$strFile = zipPath($intApplicationNumber);
clearstatcache();
if(!file_exists($strFile)){
return responseInternalError('ZIP file does not exist', $strFile);
}
Die intApplicationNumber
wird ein Anforderungsparameter (zB 12345678
.), Die einfach durch die auf einen Pfad verwandelt zipPath()
Funktion (zB \Share\12\345\678.zip
- immer ein voller Pfad).
Das Skript kann gleichzeitig mit verschiedenen Anwendungsnummern aufgerufen werden, wird jedoch nicht gleichzeitig mit derselben Anwendungsnummer aufgerufen.
Wenn das Skript fehlschlägt (gibt den 'ZIP file does not exist'
Fehler zurück), wird es eine Minute später erneut aufgerufen. Wenn dies fehlschlägt, wird es dauerhaft als fehlgeschlagen markiert. Dann, in der Regel mehr als eine Stunde später, kann ich die Skript aufrufen manuell mit dem gleichen Aufruf (GET Anfrage), dass es auf der Produktion fertig ist und es funktioniert gut, die Datei gefunden wird und in der Antwort gesendet:
public static function ResponseRaw($strFile){
ob_end_clean();
self::ReadFileChunked($strFile, false);
exit;
}
protected static function ReadFileChunked($strFile, $blnReturnBytes=true) {
$intChunkSize = 1048576; // 1M
$strBuffer = '';
$intCount = 0;
$fh = fopen($strFile, 'rb');
if($fh === false){
return false;
}
while(!feof($fh)){
$strBuffer = fread($fh, $intChunkSize);
echo $strBuffer;
if($blnReturnBytes){
$intCount += strlen($strBuffer);
}
}
$blnStatus = fclose($fh);
if($blnReturnBytes && $blnStatus){
return $intCount;
}
return $blnStatus;
}
Nachdem der Client die Datei erhalten hat, benachrichtigt er den PHP-Server, dass die Datei an einen Speicherort im Archiv verschoben werden kann (mittels copy()
und unlink()
). Dieser Teil funktioniert gut.
STRACE Ergebnis
Nach mehreren Tagen ohne Fehler, tauchte der Fehler auf. Ich lief strace
und berichtet
access("/Share/11/222/333.zip", F_OK) = -1 ENOENT (No such file or directory)
für einige Dateien, die existieren, wenn ich ls /Share/11/222/333.zip
von der Kommandozeile ausgeführt werden. Daher liegt das Problem auf Betriebssystemebene, PHP ist nicht zu verantworten.
Die Fehler traten auf, wenn die Auslastung der Festplatte auf dem Host (aufgrund anderer Prozesse) anstieg. Daher scheint @ Riskyasins Vorschlag am wahrscheinlichsten zu sein - es handelt sich um ausgelastete Ressourcen/Zeitüberschreitungen.
Ich werde versuchen, @ Miguel-Svq der Rat der überspringen der Existenz Test und einfach für fopen()
sofort gehen und den Fehler dann behandeln. Ich werde sehen, ob sich etwas ändert.
Gute Frage. Es ist nicht das erste Mal, dass ich so etwas als unzuverlässig empfinde. Ein Workaround, der Ihnen ein wenig hilft, könnte sein, die file_exists erneut zu versuchen und das Skript nicht sofort zu stoppen. – DanFromGermany
Danke @DanFromGermany - ja, es ist eine der schmutzigen Ideen, die ich hatte - wiederhole es (auch nach einer Pause von N Sekunden), falls es sich um eine Art vorübergehenden Schluckauf handelt. Aber ich möchte wirklich verstehen, warum das passiert und es in der Wurzel reparieren. –
Ich glaube nicht wirklich, dass es um PHP geht, sondern um NFS. Es kann zu Zeitüberschreitungen oder ausgelasteten Ressourcen kommen, da diese auf Vernetzung angewiesen sind. 'strace' und' tcpdump' auf beiden Seiten, um zu sehen, was tatsächlich passiert, können Ihnen Hinweise geben. Versuchen Sie auch mit Benutzer von PHP/Webserver während des Testens. – risyasin