2008-11-21 24 views
27

मेरे पास एक ही मूल निर्देशिका में दो निर्देशिका हैं। मूल निर्देशिका आधार और बच्चों निर्देशिका अल्फा और ब्रावो पर कॉल करें। मैं अल्फाब्रेवो के साथ प्रतिस्थापित करना चाहता हूं। सबसे सरल तरीका है:एक निर्देशिका को परमाणु रूप से

rm -rf alpha 
mv bravo alpha 

एमवी कमांड परमाणु है, लेकिन आरएम-आरएफ नहीं है। अल्फा पर ब्रावो के साथ परमाणु रूप से प्रतिस्थापित करने का एक आसान तरीका है? यदि नहीं, तो क्या कोई जटिल तरीका है?

परिशिष्ट:

से करके, यह एक दुर्गम समस्या नहीं है अगर निर्देशिका एक छोटी अवधि के लिए मौजूद नहीं है। अल्फा तक पहुंचने का प्रयास करने वाली केवल एक ही जगह है, और यह जांचता है कि क्या कुछ भी महत्वपूर्ण करने से पहले अल्फा मौजूद है। यदि नहीं, तो यह एक त्रुटि संदेश देता है। लेकिन यह अच्छा होगा अगर ऐसा करने का कोई तरीका था। :) हो सकता है कि इनोड को सीधे संशोधित करने के लिए कुछ तरीका है, या कुछ ...

+3

परिशिष्ट में आपका परीक्षण सुरक्षित नहीं है - वहाँ एक दौड़ शर्त है। विचार करें कि क्या होता है यदि चेक पहले चलता है (और अल्फा मौजूद है) और फिर दूसरी प्रक्रिया को अल्फा हटाते समय स्विच किया जाता है, और उसके बाद इसे अब जारी रखने के लिए स्विच किया जाता है, अल्फा अब गायब हो जाता है। – Oddthinking

उत्तर

14

यदि आप सिमलिंक का उपयोग कर सकते हैं।,

$ ls -l 
lrwxrwxrwx alpha -> alpha_1 
drwxr-xr-x alpha_1 
drwxr-xr-x alpha_2 

अल्फा alpha_2 का उल्लेख करने के लिए उपयोग ln -nsf:: यहाँ है कि स्विच से पहले कैसा दिखता है

$ rm -rf alpha_1 

:

$ ln -nsf alpha_2 alpha 
$ ls -l 
lrwxrwxrwx alpha -> alpha_2 
drwxr-xr-x alpha_1 
drwxr-xr-x alpha_2 

अब आप पुराने निर्देशिका को हटा सकते हैं ध्यान दें कि यह वास्तव में पूरी तरह से परमाणु संचालन नहीं है, लेकिन यह बहुत जल्दी होता है क्योंकि "ln" कमांड दोनों अनलिंक करता है और फिर तुरंत सिम्लिंक को पुन: प्रयास करता है।

$ strace ln -nsf alpha_2 alpha 
... 
symlink("alpha_2", "alpha")    = -1 EEXIST (File exists) 
unlink("alpha")       = 0 
symlink("alpha_2", "alpha")    = 0 
... 

आप इस प्रक्रिया के रूप में वांछित को दोहरा सकते हैं:: आप strace के साथ इस व्यवहार को सत्यापित कर सकते हैं जैसे कि आप एक नया संस्करण, alpha_3 है जब:

$ ln -nsf alpha_3 alpha 
$ rm -rf alpha_2 
+0

लिनक्स वीएफएस एकाधिक निर्देशिका हार्डलिंक्स का समर्थन नहीं करता है। कुछ अन्य * निक्सों में सीमित समर्थन है, जो सुपरसुर तक सीमित है। आपको अभी भी उपनिर्देशिकाओं और फ़ाइलों के सभी अनाथ लिंक एकत्र करना होगा। – JimB

+0

हां, यह आम तौर पर लागू होने के लिए एक नरम लिंक होना चाहिए। मैंने अपनी प्रतिक्रिया संपादित की है। हालांकि मुझे विश्वास नहीं है कि जब तक अल्फा हमेशा एक लिंक होता है, तब तक कोई अनाथ होगा, जिसका अर्थ है कि मैं थोड़ा सा सवाल बदल रहा हूं। बेशक, आपको हमेशा डीआईआर –

+0

के पिछले संस्करण को हटाना होगा; बाहर निकलता है कि आपको भी झंडा चाहिए, अन्यथा आप मूल निर्देशिका के तहत एक सिम्लिंक बनाना समाप्त कर देंगे। मैंने वास्तव में प्रश्न पोस्ट करने से पहले आपके विचार की कोशिश की, और यह काम नहीं किया, लेकिन जब मैंने फिर से देखा और झंडा देखा, तो उसने ऐसा किया। इसके अलावा, जो भी आपको नीचे वोट देता है उस पर झुकाव :) – dirtside

0

मुझे विश्वास नहीं है कि ऐसा करने के लिए कोई परमाणु तरीका है। आपकी सबसे अच्छी शर्त इस तरह कुछ करना है:

mv alpha delme 
mv bravo alpha 
rm -rf delme 
6

यदि आप दोनों परिचालनों में परमाणु का मतलब है, तो मुझे विश्वास नहीं है। निकटतम होगा:

mv alpha delta 
mv bravo alpha 
rm -rf delta 

लेकिन उसमें अभी भी एक छोटी सी खिड़की होगी जहां अल्फा मौजूद नहीं था। जबकि यह वहां नहीं है

कुछ भी अल्फा का उपयोग करने की कोशिश कर की संभावना को कम करने के लिए आप जा सकते थे (आप अधिकार है तो):

nice --20 (mv alpha delta ; mv bravo alpha) 
rm -rf delta 

जो काफी हद तक अपनी प्रक्रिया प्राथमिकता अप क्रैंक जाएगा, जबकि mv संचालन हो रहा है।

रूप में आप अपने परिशिष्ट में कहते हैं, वहाँ केवल एक ही जगह की जाँच करता है कि अल्फा और यह त्रुटियों अगर यह वहां नहीं है, तो आप तुरंत त्रुटि नहीं है कि कोड को बदल सकता है, लेकिन कम समय में पुन: प्रयास करें (आसानी से उप-दूसरे है, तो दो mv संचालन के लिए) - इन रीट्रीज़ को किसी भी समस्या को कम करना चाहिए जबतक कि आप अल्फा को बहुत अक्सर बदल रहे हों।

+0

यह उतना तेज है जितना आप इसे खोल में कर सकते हैं; आप दो निर्देशिकाओं को स्थानांतरित करने के लिए सी का एक कस्टम टुकड़ा लिख ​​सकते हैं जो समय अंतराल से कुछ मिलीसेकंड को दाढ़ी देगा, या पर्ल स्क्रिप्ट का उपयोग करें (या अपना स्वयं का जहर चुनें)। यद्यपि 'आरएम-एफआर' को फिर से लिखने में कोई बात नहीं होगी। –

1

भले ही आप सीधे इनोड तक पहुंच रहे हों, फिर भी उपयोगकर्ता-स्थान में इनोड मानों को परमाणु रूप से स्वैप करने का कोई तरीका नहीं होगा।

मान लीजिए कि अल्फा निर्देशिका alpha_1 करने के लिए एक सिमलिंक है, और आप alpha_2 को इंगित करने के सिमलिंक स्विच करना चाहते हैं:

6

एक सेमाफोर के रूप में कार्य करने के लिए एक अलग, इसकी गारंटी परमाणु, आपरेशन का प्रयोग करें।

तो, अगर बनाने और एक फाइल को हटाने के संचालन परमाणु कर रहे हैं:

1) एक फ़ाइल "सेमाफोर" कहा जाता है पैदा करते हैं।

2) और है कि केवल अगर सफल() मौजूदा फ़ाइल के साथ कोई विवाद, आपरेशन (या तो प्रक्रिया अल्फा निर्देशिका, प्रक्रिया के आधार पर कर सकते हैं या ले जाने के)

3) rm सेमाफोर है।

+0

जो केवल तभी मदद करेगा जब अल्फा पर होने वाला कोई भी ऑपरेशन पहले से ही 'सेमफोर' की जांच के लिए फिर से लिखा गया हो और सेमफोर को लॉक करने में सक्षम होने के लिए प्रतीक्षा करें .. और यदि वे आपको अपना सेमफोर बनाने से रोकते हैं ऑपरेशन। – PypeBros

+0

@PypeBros: हाँ। यदि आप ऑपरेशन करने से पहले इसे जांच नहीं सकते हैं, तो इसे सैमफोर के रूप में उपयोग नहीं किया जा रहा है।यदि इसे दो समवर्ती प्रक्रियाओं द्वारा बनाया जा सकता है, तो यह एक सेमफोर नहीं है। – Oddthinking

0

कुछ ध्यान में रखना यह है कि यदि आपकी प्रक्रिया में अल्फा में कोई भी फाइल खुली है, तो इस चाल/हटाए जाने पर प्रक्रिया दिखाई नहीं देगी और फ़ाइल बंद होने पर अंत में हटाए गए किसी भी डेटा को खो दिया जाएगा और अंततः हटा दिया जाएगा।

1

ऑपरेशन की परमाणु प्रकृति के बारे में चिंता करना व्यर्थ है। बात यह है कि, दूसरे कार्य द्वारा अल्फा तक पहुंच परमाणु नहीं होगा।

ओडथिंकिंग का सेमफोर दृष्टिकोण जाने का एकमात्र तरीका है।

यदि आप अन्य कार्य को संशोधित नहीं कर सकते हैं तो आपको यह सुनिश्चित करना होगा कि यह प्रतिस्थापन करने से पहले नहीं चल रहा है।

-2

आप क्यों नहीं बस की तरह कुछ भी नहीं करते:

rm -rf alpha/* 
mv bravo/* alpha/ 
rm -rf bravo/ 

मतलब यह होगा कि अल्फा में सब कुछ नष्ट हो जाता है, अल्फा कभी नहीं नष्ट कर दिया जाता है, और सभी सामग्री को ले जाया मिलता है।

4

SQLite प्रलेखन अनुभाग File Locking and Concurrency in SQLite Version 3 एक दुर्घटना के बाद साथ-साथ पठन, अनन्य लेखन, और रोलबैक नियंत्रित करने के लिए अपने बढ़ते ताला प्रोटोकॉल की एक अच्छी तरह से लिखा विवरण नहीं है। उनमें से कुछ विचार यहां लागू होते हैं।

0

एमवी और एलएन परमाणु संचालन के लिए इस्तेमाल किया जा सकता है। मैंने एलएन (1) परमाणु रूप से वेब अनुप्रयोगों को तैनात करने के लिए उपयोग किया है।

एक सिमलिंक को बदलने के लिए सही तरीका ln -nsf

ln -nsf <target> <link_name> 

उदा साथ है

$ mkdir dir1 
$ mkdir dir2 
$ ln -s dir1 mylink 
$ ls -l mylink 
lrwxrwxrwx 1 phil phil 4 Nov 16 14:45 mylink -> dir1 
$ ln -nsf dir2 mylink 
$ ls -l mylink 
lrwxrwxrwx 1 phil phil 4 Nov 16 14:46 mylink -> dir2 
+3

ln -nsf तेज़ है लेकिन यह वास्तव में परमाणु नहीं है। एलएन प्रक्रिया वास्तव में अनलिंक करती है और फिर तुरंत सिम्लिंक को दोबारा शुरू करती है। आप इसे स्ट्रेस के साथ सत्यापित कर सकते हैं। देखें http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically –

35

अंतिम समाधान symlink- और नाम बदलने-दृष्टिकोण के संयोजन है:

mkdir alpha_real 
ln -s alpha_real alpha 

# now use "alpha" 

mkdir beta_real 
ln -s beta_real tmp 

# atomically rename "tmp" to "alpha" 
# use -T to actually replace "alpha" instead of moving *into* "alpha" 
mv -T tmp alpha 
बेशक

, आवेदन तक पहुँचने अल्फा राह में बदल रहा है सिमलिंक के साथ सौदा करने में सक्षम हो गया है।

+4

http://rcrowley.org/2010/01/06/things-unix-can-do -atomically.html 'एमवी' के' -T' ध्वज के स्पष्टीकरण के लिए जो परमाणु रूप से दो सिम्लिंकों को स्वैप करने की अनुमति देता है। – PypeBros

5

डेविड का समाधान यहाँ है, जो पूरी तरह से परमाणु है पर प्राप्त करें ... समस्या सिर्फ आपको लगता है कि mv के लिए -T विकल्प गैर POSIX है, और इसलिए कुछ POSIX OSes यह समर्थन नहीं कर सकते है में चलाने चाहते हैं (FreeBSD, सोलारिस, आदि ... http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html)।

mkdir -p tmp/real_dir1 tmp/real_dir2 
touch tmp/real_dir1/a tmp/real_dir2/a 
# start with ./target_dir pointing to tmp/real_dir1 
ln -s tmp/real_dir1 target_dir 
# create a symlink named target_dir in tmp, pointing to real_dir2 
ln -sf tmp/real_dir2 tmp/target_dir 
# atomically mv it into ./ replacing ./target_dir 
mv tmp/target_dir ./ 

exaple के माध्यम से:

mkdir bravo_dir alpha_dir 
ln -s bravo_dir bravo 
ln -s alpha_dir alpha 
mv -fT bravo alpha 

strace: http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/

3

इस चाल करना चाहिए मामूली संशोधन के साथ, इस दृष्टिकोण पूरी तरह से परमाणु, और सभी POSIX OSes भर में पोर्टेबल होने के लिए बदला जा सकता है एमवी-एफटी ब्रावो अल्फा शो:

rename("bravo", "alpha") 

जो सुंदर परमाणु टी दिखता है ओ मैं

0

यह भी एक ही बार में कुछ उपसर्ग (यहाँ Z) unionfs-fuse का उपयोग करने में सामग्री की एक पूरी भागों को बदलने के लिए संभव है:

# mkdir a b c Z 
# touch a/1 b/2 c/3 
# ln -s a X 
# ln -s b Y 
# unionfs X=RW:Y=RW Z 
# shopt -s globstar 
# file ** 
a: directory 
a/1: empty 
b: directory 
b/2: empty 
c: directory 
c/3: empty 
X: symbolic link to a 
Y: symbolic link to b 
Z: directory 
Z/1: empty 
Z/2: empty 
# ln -sfn c Y 
# file **/* 
a: directory 
a/1: empty 
b: directory 
b/2: empty 
c: directory 
c/3: empty 
X: symbolic link to a 
X/1: empty 
Y: symbolic link to c 
Y/3: empty 
Z: directory 
Z/1: empty 
Z/3: empty 
# fusermount -u Z 
# rm -r a b c X Y Z 
संबंधित मुद्दे