एक सिम्लिंक लूप्स तय करने के लिए एक एल्गोरिथ्म है?


16

यूनिक्स सिस्टम आमतौर पर सिर्फ त्रुटि करते हैं यदि वे एक ऐसे मार्ग से भिड़ जाते हैं जिसमें एक सिम्पीनल लूप होता है या सिर्फ बहुत सारे सिम्बलिंक्स होते हैं, क्योंकि उनके पास एक पथ लुकअप में पार करने वाले सिमिलिंक की संख्या की सीमा होती है। लेकिन क्या वास्तव में यह तय करने का एक तरीका है कि क्या एक दिया हुआ रास्ता किसी चीज का समाधान करता है या एक लूप होता है, भले ही इसमें एक यूनिक्स की तुलना में अधिक लिंक हों जो पालन करने के लिए तैयार हैं? या यह एक औपचारिक रूप से अवांछनीय समस्या है? और अगर यह तय किया जा सकता है, तो क्या यह समय की उचित मात्रा में तय किया जा सकता है / मेमोरी (जैसे बिना किसी फाइल पर सभी फाइलों को देखने के)?

कुछ उदाहरण:

a/b/c/d
where a/b is a symlink to ../e
and e is a symlink to f
and f is a symlink to a/b

a/b/c/d
where a/b/c is a symlink to ../c

a/b/c/d
where a/b/c is a symlink to ../c/d

a/b/c/d
where a/b/c is a symlink to /a/b/e
where a/b/e is a symlink to /a/b/f
where a/b/f is a symlink to /a/b/g

संपादित करें :

स्पष्ट करने के लिए, मैं फाइल सिस्टम में लूप खोजने के बारे में नहीं पूछ रहा हूं, मैं एक निर्णय एल्गोरिथ्म के बारे में पूछ रहा हूं जो किसी दिए गए मार्ग का निर्णय करता है कि क्या यह एक निश्चित फ़ाइल / निर्देशिका में हल होता है या क्या यह बिल्कुल भी हल नहीं करता है। निम्नलिखित प्रणाली में उदाहरण के लिए, एक लूप है, लेकिन दिए गए मार्ग अभी भी ठीक हल करता है:

/ -- a -- b
where b is a symlink to /a

इस निर्देशिका पेड़ में स्पष्ट रूप से एक चक्र है, लेकिन पथ a/b/b/b/b/bअभी भी ठीक हल करता है /a


readlink ...उपरोक्त स्थितियों के बारे में कमांड लाइन टूल क्या कहता है?
स्लम

1
क्या आप पूछ रहे हैं कि क्या हम पाथनाम से सिर्फ यह बता सकते हैं कि क्या लूप हैं? या क्या हम एक वास्तविक ऑपरेटिंग सिस्टम में मानक टूल का उपयोग करके और पाथनाम के विभिन्न घटकों को जांचने के लिए क्या कर सकते हैं?
बजे माइक डाइहन

@MikeDiehn जाहिर तौर पर किसी को केवल एक पथ से नहीं बताया जा सकता है अगर वह बिना फाइल सिस्टम ऑपरेशन के हल करता है। लेकिन यह भी एक ओएस वातावरण के साथ एक पथ को भेद करने के लिए सीधा नहीं है जो केवल एक से हल करने के लिए बहुत सारे सिम्बलिंक की आवश्यकता होती है जो बिल्कुल भी हल नहीं करता है।
जनकानि '

जवाबों:


10

मुझे पूरी तरह से समझ में नहीं आ रहा है कि आप क्या पूछ रहे हैं। अगर मुझे कोई बेहतर पता नहीं था, तो मुझे लगता है कि आप पूछ रहे थे कि क्या फ़ाइल से निपटने के बीच में इसका पता लगाने का कोई तरीका था। मुझे विश्वास नहीं होता कि यह संभव है।

एकमात्र विधि जिसकी मैं गर्भधारण कर सकता हूं वह एक ऐसा स्थान है जहां आप विशेष रूप से निर्देशिका पेड़ में एक विशेष शाखा के माध्यम से देखना शुरू करते हैं।

उदाहरण

$ tree 
.
`-- a
    `-- b
        |-- c
        |   `-- d
        |       `-- e -> ../../../../a/b
        `-- e -> e

5 directories, 1 file

findआदेश इस पाश का पता लगाने जाएगा, लेकिन नहीं वास्तव में आप इसके बारे में एक पूरी बहुत कुछ बता सकते हैं।

$ find -L . -mindepth 15
find: File system loop detected; `./a/b/c/d/e' is part of the same file system loop as `./a/b'.
find: `./a/b/e': Too many levels of symbolic links

मैंने मनमाने ढंग से 15 स्तर उठाए ताकि किसी भी आउटपुट को प्रदर्शित किया जा सके find। हालाँकि आप उस स्विच को बंद कर सकते हैं ( -mindepth) यदि आप डायरेक्टरी ट्री के प्रदर्शित होने की परवाह नहीं करते हैं। findआदेश अभी भी पाश और बंद हो जाता है का पता लगाता है:

$ find -L . 
.
./a
./a/b
./a/b/c
./a/b/c/d
find: File system loop detected; `./a/b/c/d/e' is part of the same file system loop as `./a/b'.
find: `./a/b/e': Too many levels of symbolic links

संयोग से, यदि आप डिफॉल्ट को ओवरराइड करना चाहते हैं MAXSYMLINKSजो स्पष्ट रूप से 40 लिनक्स पर है (कर्नेल के नए 3.x संस्करण) तो आप इस U & L Q & A शीर्षक को देख सकते हैं: आप MAXSYMLINKS कैसे बढ़ा सकते हैं

सिमिलिंक कमांड का उपयोग करना

एक उपकरण है जिसे एफ़टीपी साइट अनुरक्षक कह सकते हैं symlinks जो टूल लंबी या लटकते पेड़ों के साथ मुद्दों को उजागर करने में मदद करेगा जो प्रतीकात्मक लिंक के कारण थे।

कुछ मामलों में symlinksटूल का उपयोग अपमानजनक लिंक को हटाने के लिए भी किया जा सकता है।

उदाहरण

$ symlinks -srv a
lengthy:  /home/saml/tst/99159/a/b/c/d/e -> ../../../../a/b
dangling: /home/saml/tst/99159/a/b/e -> e

शानदार पुस्तकालय

Glibc लाइब्रेरी इसके चारों ओर कुछ C फंक्शंस पेश करती है, लेकिन मैं पूरी तरह से उनकी भूमिका या वास्तव में उनका उपयोग कैसे करना है, यह नहीं जानता। इसलिए मैं केवल उन्हें आपको इंगित कर सकता हूं।

मैन पेज, man symlinkफंक्शन नामक फंक्शन की परिभाषा को दर्शाता है symlink()। विवरण इस प्रकार है:

symlink () newpath नाम का एक प्रतीकात्मक लिंक बनाता है जिसमें स्ट्रिंग ओल्डपथ होता है।

एक त्रुटि बताती है कि यह फ़ंक्शन लौटाता है:

ELOOP नएपथ को हल करने में कई प्रतीकात्मक लिंक सामने आए।

मैं आपको मैन पेज पर भी निर्देशित करूंगा, man path_resolutionजिसमें चर्चा की गई है कि कैसे यूनिक्स डिस्क पर आइटम के लिए पथ निर्धारित करता है। विशेष रूप से यह पैराग्राफ।

If  the component is found and is a symbolic link (symlink), we first 
resolve this symbolic link (with the current lookup directory as starting 
lookup directory).  Upon error, that error is returned.  If the result is 
not a directory, an ENOTDIR error is returned.  If the resolution of the 
symlink is successful and returns a directory, we set the current lookup
directory to that directory, and go to the next component.  Note that the 
resolution process here involves recursion.  In order  to  protect  the 
kernel against stack overflow, and also to protect against denial of 
service, there are limits on the maximum recursion depth, and on the maximum 
number of symbolic links followed.  An ELOOP error is returned  when  the
maximum is exceeded ("Too many levels of symbolic links").

यदि संभव हो तो मैं एक सिंगल पाथ दिए जाने पर एक सिम्लिंक लूप का पता लगाने का एक तरीका चाहूंगा, और ओएस को ऐसा करने के बजाय एक प्रोग्राम में मैन्युअल रूप से सिमिलिंक को हल करना चाहूंगा। लेकिन मैं सोच रहा हूं कि क्या यह बिल्कुल संभव है। खोज समाधान दिलचस्प लगता है, लेकिन क्या आपके पास कोई विचार है / कैसे / पाएं सहानुभूति छोरों का पता लगाता है, और यदि इसका उपयोग करने का तरीका पूरा हो गया है (यानी सभी संभावित छोरों का पता लगाता है और किसी भी गैर-लूपिंग पथ को गलत नहीं करता है)?
जनकानी '

@Somejan - ए को मेरे अपडेट देखें। मुझे पता है कि अगर समझ में आता है।
स्लम

5

ठीक है, कुछ और विचारों के बाद मुझे लगता है कि मेरे पास एक स्पष्ट समाधान है।

आलोचनात्मक अंतर्दृष्टि यह है कि यदि प्रत्येक लिंक जो किसी पथ का हिस्सा है, किसी चीज़ का समाधान करता है, तो संपूर्ण पथ हल हो जाता है। या दूसरे रास्ते के आसपास, यदि कोई मार्ग हल नहीं करता है, तो एक विशिष्ट सिमलिंक होना चाहिए जिसे ट्रैवर्सिंग की आवश्यकता होती है जो हल नहीं करता है।

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

यदि एल्गोरिथ्म इस बात का ट्रैक रखता है कि यह वर्तमान में किस सिम्लिंक को हल कर रहा है (या पुनरावर्ती लिंक के मामले में कौन सी सहानुभूति है), तो यह पता लगा सकता है कि क्या वह पुन: पुनरावर्ती रूप से किसी लिंक को हल करने का प्रयास कर रहा है जो अभी भी हल करने में व्यस्त है।

कलन विधि:

initialize `location` to the current working directory
initialize `link_contents` to the path we want to resolve
initialize `active_symlinks` to the empty set

def resolve_symlink(location, link_contents, active_symlinks) :
    loop forever:
        next_location = location / [first element of link_contents]
        see if next_location is a symlink.
        if so:
            if next_location in active_symlinks: abort, we have a loop
            location = resolve_symlink(location, readlink(next_location), active_symlinks ∪ {next_location})
        else:
            location = next_location
        strip first element of link_contents
        if link_contents is empty: 
            return location

संपादित करें :

मेरे पास https://thbucket.org/JanKanis/python-inotify/src/853ed903e870cbfa283e6ce7a5a41aeffe16d4e7/inotify/pathresolver.py?at=pathwatch पर इस कार्य का कार्यान्वयन है।


3

पायथन में एक फ़ंक्शन है जिसे networkx.simple_cycles () कहा जाता है जो इसके लिए उपयोग किया जा सकता है। लेकिन हाँ इसे सिस्टम की हर फाइल को पढ़ना होगा।

>>> import networkx as nx
>>> G = nx.DiGraph()
>>> G.add_edge('A', 'B')
>>> G.add_edge('B', 'C')
>>> G.add_edge('C', 'D')
>>> G.add_edge('C', 'A')
>>> nx.simple_cycles(G)
[['A', 'B', 'C', 'A']]

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

@Somejan: एक फाइल सिस्टम नाम स्थान है एक ग्राफ, और एक फ़ाइल नाम एक रास्ता है कि ग्राफ़ पर चुना है।
नवजाल

@ninjalj: हाँ एक फाइल सिस्टम एक ग्राफ है, लेकिन मुझे नहीं लगता कि एक फ़ाइल नाम है बस कि ग्राफ पर एक पथ। फ़ाइलनाम को ग्राफ़ को कैसे पार करना है, इस पर निर्देशों के एक सेट के रूप में देखा जा सकता है। यहां तक ​​कि अगर ग्राफ़ में चक्र शामिल हैं, जिसका अर्थ यह नहीं है कि एक फ़ाइल नाम जो उस चक्र का अनुसरण करता है, तो वह हल नहीं करता है, मेरा उदाहरण मेरी पिछली टिप्पणी में देखें।
जनकवि ०

3

एक मौन प्रणाली पर (जब कोई परिवर्तन नहीं हो रहा है), हाँ, एक एल्गोरिथ्म है। प्रतीकात्मक लिंक की एक सीमित संख्या है, इसलिए वे एक परिमित ग्राफ का गठन करते हैं, और चक्रों का पता लगाना एक अंतिम प्रक्रिया है।

एक जीवित प्रणाली पर, चक्रों का पता लगाने का कोई तरीका नहीं है, क्योंकि प्रतीकात्मक लिंक बदल सकते हैं, जबकि चक्र डिटेक्टर चल रहा है। प्रत्येक प्रतीकात्मक लिंक को पढ़ना परमाणु है, लेकिन प्रतीकात्मक लिंक का अनुसरण करना नहीं है। यदि कर्नेल कुछ कर्लिंग बदल रहा है, जबकि कर्नेल ट्रैवर्सल कर रहा है, तो यह अलग-अलग लिंक वाले अनंत मार्ग पर समाप्त हो सकता है।


98-99% सटीकता तक लाने के लिए उन परिवर्तनों को कम करने के तरीके हैं। आप इसे फ़ाइलों पर समय टिकटों पर ध्यान दे सकते हैं और मैं वास्तव में लिंक का अनुसरण करने का सुझाव नहीं दूंगा। चूंकि यह रूट से पुनरावर्ती है, इसलिए इसे वास्तविक निर्देशिका बाद में मिलेगी।
Back2Basics

1
@ Back2Basics ये नंबर पूरी तरह से अर्थहीन हैं। यह एक कर्नेल इंटरफ़ेस है। यदि यह हर समय काम नहीं करता है, तो यह काम नहीं करता है, अवधि।
गिल्स एसओ- बुराई को रोकना '

2

पास के रूप में मैं वर्तमान लिनक्स कर्नेल स्रोतों को देखने से बता सकता हूं, सभी कर्नेल करता है कि कितने लिंक का अनुसरण किया जाता है, और यह गणना करता है कि क्या यह किसी संख्या से बड़ा है। टिप्पणी, और फ़ंक्शन के लिए namei.c में लाइन 1330 देखें nested_symlink()। ELOOP मैक्रो (त्रुटि संख्या एक से लौटी हैread(2) इस स्थिति के लिए सिस्टम कॉल ) उस फ़ाइल में कई स्थानों पर दिखाई देता है, इसलिए हो सकता है कि यह लिंक के बाद के लिंक की तरह सरल न हो, लेकिन यह निश्चित है कि यह कैसा दिखता है।

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


व्यावहारिक उपयोग के लिए, बस ट्रैवर्स किए गए लिंक की संख्या की गिनती ठीक है, खासकर जब से कि कर्नेल करता है, इसलिए भले ही आप सही तरीके से हल करने वाले पथ से मुठभेड़ करें, जिसमें बहुत सारे सिम्बलिंक्स हैं, फिर भी आप उस पथ का उपयोग किसी भी व्यावहारिक के लिए नहीं कर सकते हैं ( इसका मतलब है कि मैन्युअल रूप से
सहानुभूति
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.