vim - विम "सूडो के साथ लिखने" चाल कैसे काम करता है?




sudo (5)

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

:w !sudo tee %

बात यह है कि मुझे यह नहीं मिलता कि वास्तव में क्या हो रहा है।

मैंने पहले ही यह पाया है: w इसके लिए है

                                                        *:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
                        Execute {cmd} with [range] lines as standard input
                        (note the space in front of the '!').  {cmd} is
                        executed like with ":!{cmd}", any '!' is replaced with
                        the previous command |:!|.

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

!sudo tee भाग प्रशासक विशेषाधिकारों के साथ tee कहते हैं।

सभी को समझने के लिए, % को फ़ाइल नाम ( tee लिए पैरामीटर के रूप में) आउटपुट करना चाहिए, लेकिन मुझे इस व्यवहार के लिए मदद पर संदर्भ नहीं मिल सकते हैं।

tl; क्या कोई मुझे इस आदेश को विच्छेदन करने में मदद कर सकता है?


% मतलब है "वर्तमान फाइल"

चूंकि यूजीन वाई ने बताया , % मतलब वास्तव में "वर्तमान फ़ाइल नाम" है। विम में इसके लिए एक और उपयोग प्रतिस्थापन आदेशों में है। उदाहरण के लिए, :%s/foo/bar अर्थ है " वर्तमान फ़ाइल में , bar साथ foo घटनाओं को प्रतिस्थापित करें।" यदि आप टाइप करने से पहले कुछ टेक्स्ट हाइलाइट करते हैं :s , आप देखेंगे कि हाइलाइट की गई रेखाएं आपकी प्रतिस्थापन सीमा के रूप में % की जगह लेती हैं।

:w आपकी फाइल अपडेट नहीं कर रहा है

इस चाल का एक भ्रमित हिस्सा यह है कि आप सोच सकते हैं :w आपकी फाइल को संशोधित कर रहा है, लेकिन ऐसा नहीं है। अगर आपने file1.txt खोला और संशोधित किया, तो चला गया :w file2.txt , यह "के रूप में सहेजें" होगा; file1.txt संशोधित नहीं किया जाएगा, लेकिन वर्तमान बफर सामग्री file2.txt भेजी file2.txt

file2.txt बजाय, आप बफर सामग्री प्राप्त करने के लिए शेल कमांड को प्रतिस्थापित कर सकते हैं । उदाहरण के लिए, :w !cat सिर्फ सामग्री प्रदर्शित करेगा।

यदि विम सुडो एक्सेस के साथ नहीं चलाया गया था, तो :w संरक्षित फ़ाइल को संशोधित नहीं कर सकता है, लेकिन यदि यह खोल में बफर सामग्री को पास करता है, तो खोल में एक कमांड सुडो के साथ चलाया जा सकता है । इस मामले में, हम tee उपयोग करते हैं।

टी समझना

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

उदाहरण के लिए, ps -ax | tee processes.txt | grep 'foo' ps -ax | tee processes.txt | grep 'foo' ps -ax | tee processes.txt | grep 'foo' , प्रक्रियाओं की सूची एक पाठ फ़ाइल में लिखी जाएगी और grep साथ पास की जाएगी।

     +-----------+    tee     +------------+
     |           |  --------  |            |
     | ps -ax    |  --------  | grep 'foo' |
     |           |     ||     |            |
     +-----------+     ||     +------------+
                       ||   
               +---------------+
               |               |
               | processes.txt |
               |               |
               +---------------+

( Asciiflow के साथ बनाया गया Asciiflow ।)

अधिक जानकारी के लिए tee मैन पेज देखें।

एक हैक के रूप में टी

स्थिति में आपका प्रश्न वर्णन करता है, tee का उपयोग करना एक हैक है क्योंकि हम जो भी करते हैं उसका आधा अनदेखा कर रहे हैंsudo tee हमारी फाइल को लिखता है और मानक आउटपुट में बफर सामग्री भी भेजता है, लेकिन हम मानक आउटपुट को अनदेखा करते हैं । हमें इस मामले में किसी अन्य पाइप कमांड को पास करने की आवश्यकता नहीं है; हम सिर्फ एक फ़ाइल लिखने के वैकल्पिक तरीके के रूप में tee का उपयोग कर रहे हैं और ताकि हम इसे sudo साथ बुला सकें।

इस चाल को आसान बनाना

इस ट्रिक को उपयोग में आसान बनाने के लिए आप इसे अपने .vimrc जोड़ सकते हैं: बस टाइप करें :w!!

" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %

> /dev/null part मानक आउटपुट को स्पष्ट रूप से फेंकता है, जैसा कि मैंने कहा था, हमें किसी अन्य पाइप कमांड पर कुछ भी पास करने की आवश्यकता नहीं है।


उपर्युक्त मैपिंग ने मेरे लिए ठीक काम किया, सूडो का उपयोग करके बचाने के लिए और अतिरिक्त कुंजी दबाए बिना फ़ाइल को फिर से लोड करने के लिए। (बस डब्ल्यू दबाएं)

map w :execute ':silent w !sudo tee % > /dev/null' <bar> :edit! <cr>

मैं अपनी फाइल खोलने के दौरान "ओप्स मैं सूडो लिखना भूल गया" के लिए एक और दृष्टिकोण सुझा सकता हूं :

एक permission denied प्राप्त करने के बजाय, और टाइप करने के लिए :w!! , मुझे एक सशर्त vim कमांड के लिए यह अधिक सुरुचिपूर्ण लगता है जो फ़ाइल स्वामी root sudo vim करता है।

यह कार्यान्वित करने में आसान है (यहां तक ​​कि अधिक सुरुचिपूर्ण कार्यान्वयन भी हो सकते हैं, मैं स्पष्ट रूप से बैश-गुरु नहीं हूं):

function vim(){
  OWNER=$(stat -c '%U' $1)
  if [[ "$OWNER" == "root" ]]; then
    sudo /usr/bin/vim $*;
  else
    /usr/bin/vim $*;
  fi
}

और यह वास्तव में अच्छी तरह से काम करता है।

यह एक vim एक से अधिक bash केंद्रित दृष्टिकोण है, इसलिए हर कोई इसे पसंद नहीं कर सकता है।

बेशक:

  • ऐसे उपयोग मामले हैं जहां यह असफल हो जाएगा (जब फ़ाइल स्वामी root नहीं root लेकिन sudo आवश्यकता है, लेकिन फ़ंक्शन को वैसे भी संपादित किया जा सकता है)
  • यह केवल समझने के लिए vim का उपयोग करते समय समझ में नहीं आता है (जहां तक ​​मेरा संबंध है, मैं छोटी फाइलों के लिए tail या cat उपयोग करता हूं)

लेकिन मुझे लगता है कि यह एक बेहतर देव उपयोगकर्ता अनुभव लाता है, जो कुछ ऐसा है जो आईएमएचओ को bash का उपयोग करते समय भुला दिया जाता है। :-)


यह भी अच्छी तरह से काम करता है:

:w !sudo sh -c "cat > %"

यह @Nathan Long की टिप्पणी से प्रेरित है।

नोटिस :

" इसके बजाए इस्तेमाल किया जाना चाहिए क्योंकि हम खोलने से पहले % विस्तारित करना चाहते हैं।


:w - एक फाइल लिखें।

!sudo - कॉल खोल sudo कमांड।

tee - लिखने का आउटपुट (vim: w) कमांड टीई का उपयोग करके रीडायरेक्ट किया गया। % वर्तमान फ़ाइल नाम यानी /etc/apache2/conf.d/mediawiki.conf के अलावा कुछ भी नहीं है। दूसरे शब्दों में टीई कमांड रूट के रूप में चलाया जाता है और यह मानक इनपुट लेता है और इसे% द्वारा दर्शाए गए फ़ाइल में लिखता है। हालांकि, यह फिर से फ़ाइल को फिर से लोड करने के लिए संकेत देगा (Vim को अपने आप में बदलाव लोड करने के लिए हिट करें):

ट्यूटोरियल लिंक





sudo