निर्धारित करें कि क्या फ़ाइल पर लिखे जाने की प्रक्रिया में है?


25

मुझे एक स्वचालित प्रक्रिया (1 मिनट क्रोन स्क्रिप्ट के माध्यम से) को तैनात करने की आवश्यकता है जो एक विशिष्ट निर्देशिका में टार फ़ाइलों की तलाश करती है। यदि एक टार फ़ाइल पाई जाती है, तो यह उचित स्थान पर अनारक्षित है और तब टार फ़ाइल हटा दी जाती है।

टार फ़ाइलों को स्वचालित रूप से SSH पर दूसरे सर्वर से इस सर्वर पर कॉपी किया जाता है। कुछ मामलों में, टार फाइलें बहुत बड़ी होती हैं, जिनमें बहुत सारी फाइलें होती हैं।

समस्या है कि मैं में चलाने के लिए उम्मीद कर रहा हूँ: अगर यह लेता है> 1 मिनट के लिए टार फ़ाइल सर्वर पर कॉपी किया जाना है, और क्रोन स्क्रिप्ट हर मिनट में एक बार चलता है, यह .tar.gz फ़ाइल को देखने और करने की कोशिश करने जा रहा है। इसे तब तक अनारक्षित करें, भले ही टार फ़ाइल अभी भी लिखे जाने की प्रक्रिया में है।

अगर किसी फ़ाइल को वर्तमान में लिखा जा रहा है, या यदि वह केवल एक आंशिक फ़ाइल है, आदि के लिए परीक्षण करने का कोई तरीका है?

एक विकल्प मैं सोच रहा था कि फ़ाइल को एक अलग फ़ाइल एक्सटेंशन (जैसे .tar.gz.part) के रूप में कॉपी किया जाना चाहिए और फिर .tar.gzहस्तांतरण पूरा होने के बाद इसका नाम बदल दिया जाएगा। लेकिन मुझे लगा कि मैं यह पता लगाने की कोशिश करूंगा कि क्या यह निर्धारित करने का एक तरीका है कि फ़ाइल पहले कमांड लाइन पर है ... कोई सुराग?


2
फ़ाइल को कैसे स्थानांतरित किया जा रहा है? उदाहरण के लिए, rsyncस्थानांतरण (डिफ़ॉल्ट रूप से) के दौरान एक अस्थायी फ़ाइल नाम का उपयोग करता है, और केवल फ़ाइल पूरी तरह से स्थानांतरित होने के बाद , इसे वास्तविक फ़ाइल नाम में बदल देता है।
पिस्कोर

जवाबों:


12

आप सही रास्ते पर हैं, फ़ाइल का नाम बदलना एक परमाणु ऑपरेशन है, इसलिए अपलोड के बाद नाम बदलना सरल, सुरुचिपूर्ण और त्रुटि नहीं है। एक अन्य दृष्टिकोण जो मैं सोच सकता हूं कि यह lsof | grep filename.tar.gzजांचने के लिए उपयोग करना है कि क्या फ़ाइल को किसी अन्य प्रक्रिया द्वारा एक्सेस किया जा रहा है।


7
( lsof filename.tar.gzऔर अधिक कुशल और की तुलना में अधिक सटीक है lsof | grep filename.tar.gz)
रिच

BTW, यह फ़ाइल नाम का एक पूर्ण पथ होना चाहिए
डेनिसली

14

lsofयदि किसी फ़ाइल को किसी प्रक्रिया द्वारा खोला गया है, यह निर्धारित करने के लिए आपका सबसे अच्छा शर्त है :

#  lsof -f -- /var/log/syslog
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
rsyslogd 1520 syslog    1w   REG  252,2    72692 16719 /var/log/syslog

आप आसानी से नहीं बता सकते हैं कि यह लिखे जाने की प्रक्रिया में है, लेकिन अगर यह लिखा जा रहा है, तो यह खुला होना चाहिए।


संपादित करें: प्रस्तावित समाधान को लागू करने के बजाय वास्तविक समस्या को हल करें!

फ़ाइल को स्थानांतरित करने के लिए rsync का उपयोग करें:

  rsync -e ssh remote:big.tar.gz .

इस तरह, फ़ाइल को मौजूदा एक के ऊपर कॉपी नहीं किया जाएगा, लेकिन एक अस्थायी फ़ाइल ( .big.tar.gz.XXXXXX) में कॉपी किया जा सकता है जब तक कि स्थानांतरण पूरा नहीं हो जाता है, तब स्थान पर ले जाया जाता है।


6

थोड़ा पुराना, लेकिन अधिकांश उत्तर पूरी तरह से प्रश्न के बिंदु को याद करते हैं:

लेकिन मुझे लगा कि मैं यह पता लगाने की कोशिश करूंगा कि क्या यह निर्धारित करने का कोई तरीका है कि फाइल पहले कमांड लाइन पर है या नहीं ...

सामान्य तौर पर, ऐसा नहीं है। यह निर्धारित करने के लिए आपके पास पर्याप्त जानकारी नहीं है।

क्योंकि यह निर्धारित करना कि फ़ाइल बंद है, यह निर्धारित करने के समान नहीं है कि फ़ाइल पूरी है या नहीं । उदाहरण के लिए, स्थानांतरण के माध्यम से कनेक्शन खो जाने पर एक फ़ाइल "बंद" हो जाएगी।

केवल @ एलेक्स के जवाब को यह अधिकार मिला। और यहां तक ​​कि वह lsofकुछ हद तक उपयोग करने के लिए गिर गया ।

यह निर्धारित करने के लिए कि फ़ाइल पूरी तरह से हो गई है, सफलतापूर्वक स्थानांतरित किए जाने के लिए अधिक डेटा की आवश्यकता होती है। जैसे कि:

एक विकल्प मैं सोच रहा था कि फ़ाइल को एक अलग फ़ाइल एक्सटेंशन (जैसे .tar.gz.part) के रूप में कॉपी किया जाना चाहिए और फिर .tar.gzहस्तांतरण पूरा होने के बाद इसका नाम बदल दिया जाएगा।

यह पूरी तरह से ठीक है कि फाइल पूरी तरह से और सफलतापूर्वक स्थानांतरित हो गई है। जब तक आप एक ही फाइल सिस्टम में रहते हैं तब तक आप एक डायरेक्टरी से दूसरी डायरेक्टरी में भी फाइल को स्थानांतरित कर सकते हैं। या प्रेषक filename.doneको संकेत पूरा होने के लिए एक खाली फ़ाइल भेजें ।

लेकिन सभी तरीकों से प्रेषक पर किसी न किसी तरह से संकेत देना है कि स्थानांतरण सफलतापूर्वक पूरा हो गया है। क्योंकि केवल प्रेषक के पास वह जानकारी है।

कुछ फ़ाइल प्रारूप (जैसे PDF) में डेटा होता है जो आपको यह निर्धारित करने की अनुमति देता है कि क्या फ़ाइल पूर्ण है। लेकिन आपको यह जानने के लिए पूरी फ़ाइल को खोलना और पढ़ना होगा।

lsofबस आपको बताएगा कि फ़ाइल अब खुली नहीं है - यह आपको नहीं बताएगी कि अब क्यों नहीं खुली है। न ही यह बताएगा कि फाइल कितनी बड़ी होनी चाहिए।


1
मैं इसे पर्याप्त नहीं बढ़ा सकता। यहाँ XY समस्या को हल करने वाला अच्छा काम।
बीफस्टर

5

ऐसा करने का सबसे अच्छा तरीका इन्क्रॉन ("इनोटिफ़ाइड क्रोन सिस्टम") का उपयोग करना है। यह आपको एक निर्देशिका पर एक इनॉटिफ़ वॉच सेट करने की अनुमति देता है जो तब आपको फ़ाइल संचालन के बारे में सूचित करेगा। इस मामले में, आपको क्लोजर राइट के लिए डीआईआर देखना चाहिए। एक बार फाइल लिखने के बाद बंद हो जाने के बाद आप अपनी कमांड को चला सकेंगे।


2

ऐसा लगता है कि lsof यह पता लगा सकता है कि फ़ाइल किस मोड के तहत खुली है:

lsof -f -- a_file
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     52391 bob    1w   REG    1,2       15 19545007 a_file

देखें कि यह 1w कहाँ कहता है? इसका मतलब है कि फ़ाइल डिस्क्रिप्टर नंबर 1 है और मोड w है, या लिखना है।


FDक्षेत्र से पता चलता है 3rमेरे लिए जब फाइल पढ़ने के लिए खुला है।
सोपालाजो डी एरियेरेज़

0

उपयोग inotifywaitकरने के बाद आप जो कर रहे हैं उसे प्राप्त कर सकते हैं - यह एक कमांड लिखने से पहले एक फ़ाइल लेखन समाप्त होने तक प्रतीक्षा करने की क्षमता है।

निम्न लगातार नई फ़ाइलों के लिए एक फ़ोल्डर देखेगा और फाइल को लिखते समय कमांड को लूप में निष्पादित करेगा।

WATCH_DIR=/directory/to/monitor
DEST_DIR=/x/y/z

/usr/bin/inotifywait --recursive --monitor --quiet -e moved_to -e close_write --format '%w%f' "$WATCH_DIR" | while read -r INPUT_FILE; do

mv "$0" "$DEST_DIR"

done

अधिक कॉन्फ़िगरेशन विकल्पों के लिए https://linux.die.net/man/1/inotifywatch देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.