2016-02-18 16 views
27

मैं एक CIFS शेयर विंडोज सर्वर 2012 से आर 2 उबंटू 14.04.2 LTS (कर्नेल 3.13.0-61-सामान्य) पर रखा इसपीएचपी file_exists कभी कभी

/आदि की तरह है CIFS शेयर पर एक फ़ाइल के लिए झूठे रिटर्न/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 

gid=5000 समूह www-data जो एक PHP प्रक्रिया चलाता है से मेल खाती है।

जब मैं www-data उपयोगकर्ता के रूप में लॉग इन कंसोल के माध्यम से चेक करता हूं तो फ़ाइलों को सही ढंग से आरोहित किया जाता है - वे पठनीय और हटाने योग्य (PHP स्क्रिप्ट द्वारा उपयोग किए जाने वाले ऑपरेशन) हैं।

PHP स्क्रिप्ट प्रति दिन लगभग 50-70 000 फ़ाइलों को संसाधित कर रहा है। फाइलें मेजबान विंडोज मशीन पर बनाई गई हैं और कुछ समय बाद लिनक्स मशीन पर चल रही PHP स्क्रिप्ट को एक नई फाइल के बारे में अधिसूचित किया गया है, यह जांचता है कि फ़ाइल मौजूद है (file_exists), इसे पढ़ता है और हटा देता है। आम तौर पर सभी ठीक काम करते हैं, लेकिन कभी-कभी (कुछ सैकड़ों से 1-2 000 प्रति दिन) PHP स्क्रिप्ट एक त्रुटि उठाती है कि फ़ाइल मौजूद नहीं है। यह कभी भी मामला नहीं होना चाहिए, क्योंकि यह केवल वास्तव में मौजूदा फाइलों के बारे में अधिसूचित है।

जब मैं मैन्युअल रूप से उन फ़ाइलों को मौजूदा नहीं होने की रिपोर्ट की जाँच करें, वे Ubuntu मशीन पर सही ढंग से सुलभ हैं और से पहले PHP स्क्रिप्ट अपने अस्तित्व की जाँच की एक निर्माण तिथि है।

फिर मैं उस फ़ाइल को लेने के लिए मैन्युअल रूप से PHP स्क्रिप्ट को ट्रिगर करता हूं और इसे बिना किसी समस्या के उठाया जाता है।

क्या मैं पहले से ही करने की कोशिश की

कई इसी तरह के सवाल कर रहे हैं, लेकिन मैं सभी सलाह थक गए हैं लगता है:

  • मैं file_exists($f)
  • फ़ाइल और निर्देशिका अनुमतियाँ जाँच से पहले clearstatcache() जोड़ा कर रहे हैं ठीक (ठीक उसी फ़ाइल उठाया जाता है सही ढंग से बाद में)
  • पथकी जाँच के लिए इस्तेमाल कियाकोई भी विशेष वर्ण के साथ एक पूर्ण पथ है - फ़ाइल पथ हमेशा प्रारूप /Share/11/222/333.zip के हैं (विभिन्न अंकों के साथ)
  • मैं noserverino शेयर माउंट पैरामीटर
  • इस्तेमाल किया मैं cache=none शेयर माउंट पैरामीटर के रूप में

/proc/fs/cifs/Stats/ प्रदर्शित करता है के लिए इस्तेमाल किया नीचे, लेकिन मुझे नहीं पता कि यहां कुछ संदिग्ध है या नहीं। सवाल में हिस्सा 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 

एक पैटर्न मुझे लगता है कि मैं देख रहा हूँ यह है कि केवल अगर सवाल में फ़ाइल पहले से संसाधित किया गया है त्रुटि उठाया है (पढ़ सकते हैं और नष्ट कर दिया) PHP स्क्रिप्ट से पहले है। कई फाइलों है कि ठीक से संसाधित और फिर संसाधित बाद में फिर से कर दिया गया हैं, लेकिन मुझे लगता है कि पहली बार के लिए संसाधित किया जाता है एक फ़ाइल के लिए कि त्रुटि कभी नहीं देखा है। पुन: प्रसंस्करण के बीच का समय 1 से लगभग 20 दिनों तक भिन्न होता है। फिर से प्रसंस्करण के लिए, फ़ाइल बस अद्यतन सामग्री के साथ विंडोज मेजबान पर एक ही पथ के अंतर्गत निर्मित किया गया है।

समस्या क्या हो सकती है? मैं बेहतर जांच कैसे कर सकता हूं? मैं कैसे तय कर सकते हैं कि समस्या PHP या ओएस पक्ष पर स्थित है?


अद्यतन

मैं सॉफ्टवेयर है कि एक उबंटू वीएम है कि एक ही शेयरों उसी तरह mounts करने के लिए फ़ाइलों का उत्पादन चले गए हैं। यह घटक जावा में कोडित है। फ़ाइलों को पढ़ने/लिखने पर मुझे कोई समस्या नहीं दिख रही है।


अपडेट - पीएचपी विवरण

सटीक PHP कोड है:

$strFile = zipPath($intApplicationNumber); 

clearstatcache(); 

if(!file_exists($strFile)){ 
    return responseInternalError('ZIP file does not exist', $strFile); 
} 

intApplicationNumber है एक अनुरोध पैरामीटर (जैसे 12345678।) जो केवल द्वारा एक पथ के लिए तब्दील हो जाता है zipPath() फ़ंक्शन (उदाहरण के लिए \Share\12\345\678.zip - हमेशा एक पूर्ण पथ)।

स्क्रिप्ट को विभिन्न अनुप्रयोग संख्याओं के साथ समवर्ती रूप से बुलाया जा सकता है, लेकिन उसी एप्लिकेशन नंबर के साथ समवर्ती रूप से नहीं बुलाया जाएगा।

यदि स्क्रिप्ट विफल हो जाती है ('ZIP file does not exist' त्रुटि देता है), तो इसे एक मिनट बाद फिर से बुलाया जाएगा। अगर यह विफल रहता है, तो इसे स्थायी रूप से असफल के रूप में चिह्नित किया जाएगा। फिर, आमतौर पर एक घंटे बाद से ज्यादा, मैं स्क्रिप्ट को मैन्युअल ही मंगलाचरण के साथ (अनुरोध प्राप्त) है कि यह उत्पादन पर किया है कॉल कर सकते हैं और यह ठीक काम करता है, फ़ाइल मिल गया है और जवाब में भेज दिया जाता है:

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; 
} 

क्लाइंट फ़ाइल प्राप्त करने के बाद, वह PHP सर्वर को सूचित करता है कि फ़ाइल को एक संग्रह स्थान पर स्थानांतरित किया जा सकता है (copy() और unlink() के माध्यम से)। वह हिस्सा ठीक काम करता है।


strace परिणाम

कोई त्रुटि के कई दिनों के बाद, त्रुटि दोबारा प्रकट हुई। मैं strace भाग गया और यह

access("/Share/11/222/333.zip", F_OK) = -1 ENOENT (No such file or directory) 

रिपोर्ट कुछ फ़ाइलों कि मौजूद है जब मैं कमांड लाइन से ls /Share/11/222/333.zip चलाने के लिए। इसलिए समस्या ओएस स्तर पर है, PHP को दोषी नहीं ठहराया जाना चाहिए।

त्रुटियों में वृद्धि हुई जब मेजबान पर डिस्क पर लोड बढ़ गया (अन्य प्रक्रियाओं के कारण), इसलिए नीचे @ risyasin का सुझाव सबसे अधिक संभावना है - यह व्यस्त संसाधन/टाइमआउट का मामला है।

मैं अस्तित्व परीक्षण को छोड़ने और बस fopen() के लिए जा रहा हूं और फिर त्रुटि को संभालने के लिए @ miguel-svq की सलाह का प्रयास करूंगा। मैं देखता हूं कि यह कुछ बदलता है या नहीं।

+1

अच्छा सवाल। यह पहली बार नहीं है जब मैंने इस मधुमक्खी की तरह कुछ अविश्वसनीय सुना। एक वर्कअराउंड जो आपको थोड़ा सा फ़ाइल_एक्सिस्ट को पुनः प्रयास करने में मदद करता है और स्क्रिप्ट को तुरंत रोक नहीं सकता है। – DanFromGermany

+0

धन्यवाद @DanFromGermany - हाँ, यह मेरे गंदे विचारों में से एक है - अगर यह किसी प्रकार का अस्थायी हिचकी है तो पुनः प्रयास करें (एन सेकेंड के विराम के बाद भी)। लेकिन मैं वास्तव में समझना चाहता हूं कि ऐसा क्यों होता है और इसे रूट में ठीक करता है। –

+3

मुझे सच में नहीं लगता कि यह php लेकिन nfs के बारे में है। नेटवर्किंग पर भरोसा करते समय टाइमआउट या व्यस्त संसाधन हो सकते हैं। वास्तव में क्या हो रहा है यह देखने के लिए दोनों पक्षों पर 'स्ट्रेस' और 'टीसीपीडम्प' आपको संकेत दे सकता है। परीक्षण करते समय php/webserver के उपयोगकर्ता के साथ भी प्रयास करें। – risyasin

उत्तर

1

आप directio विकल्प का उपयोग करने आईनोड डेटा कैशिंग कर रही पर फ़ाइलें इस पर्वत पर खोला से बचने की कोशिश कर सकते हैं:

//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,directio 0 0 
+0

[मैन पेज] (http://linux.die.net/man/8/mount.cifs) कहता है "यह विकल्प 3.7 में बहिष्कृत किया जाएगा। उपयोगकर्ताओं को कैश = किसी और के बजाय हालिया कर्नेल का उपयोग नहीं करना चाहिए"। मेरा कर्नेल 3.13 है और मेरे पास पहले से ही 'कैश = none' है। क्या 'डायरेक्टियो' का उपयोग तब समझ में आता है? –

0

यह शायद ही मेरी समस्या के लिए एक निश्चित जवाब नहीं बल्कि का सार है, क्या मैंने पाया और मैं किसके साथ बस गया।

समस्या के निचले भाग में यह निहित है कि यह ओएस है जो रिपोर्ट करता है कि फ़ाइल मौजूद नहीं है। रनिंग strace फ़ाइलें जो मौजूद नहीं है (और जब ls के साथ सूचीबद्ध दिखाई) के लिए कभी-कभी

access("/Share/11/222/333.zip", F_OK) = -1 ENOENT (No such file or directory) 

को दर्शाता है।

विंडोज शेयर होस्ट कभी-कभी भारी डिस्क लोड के अधीन था। मैंने जो किया वह शेयरों में से एक को एक अलग मेजबान में ले जाया गया ताकि लोड दोनों अब दोनों के बीच फैल सके। इसके अलावा, सिस्टम पर सामान्य भार हाल ही में थोड़ा हल्का है। जब भी मुझे फ़ाइल के बारे में त्रुटि नहीं मिलती है, तो मैं कुछ समय बाद अनुरोध पुनः प्रयास करता हूं और यह अब वहां नहीं है।

संबंधित मुद्दे