क्यों sudo बिल्ली अनुमति देता है एक खंडन लेकिन sudo विम ठीक काम करता है?


86

मैं अपने आर्क की pacman.conf फ़ाइल में एक रिपॉजिटरी स्रोत के अलावा को स्वचालित करने की कोशिश कर रहा हूं लेकिन echoअपनी शेल स्क्रिप्ट में कमांड का उपयोग कर रहा हूं। हालाँकि, यह इस तरह विफल रहता है: -

sudo echo "[archlinuxfr]" >> /etc/pacman.conf
sudo echo "Server = http://repo.archlinux.fr/\$arch" >> /etc/pacman.conf
sudo echo " " >> /etc/pacman.conf

-bash: /etc/pacman.conf: Permission denied

अगर मैं /etc/pacman.conf में मैन्युअल रूप से विम का उपयोग करके, परिवर्तन कर रहा हूँ

sudo vim /etc/pacman.conf

और :wqवीम का हवाला देते हुए , सब कुछ ठीक है और मेरे pacman.conf को "अनुमति से वंचित" शिकायतों के बिना मैन्युअल रूप से अपडेट किया गया है।

ऐसा क्यों है? और मुझे sudo echoकाम कैसे करना है ? (btw, मैंने sudo catभी उपयोग करने की कोशिश की, लेकिन वह अनुमति के साथ विफल रहा)


जवाबों:


51

समस्या यह है कि पुनर्निर्देशन आपके मूल शेल द्वारा संसाधित किया जा रहा है, द्वारा नहीं sudo। गोले दिमाग को पढ़ने में सक्षम नहीं हैं और यह नहीं जानते कि यह विशेष रूप >>से इसके लिए है sudoऔर इसके लिए नहीं है।

आपको:

  1. पुनर्निर्देशन को उद्धृत करें (इसलिए इसे पास किया गया है sudo)
  2. और उपयोग करें sudo -s(ताकि sudoउद्धृत पुनर्निर्देशन को संसाधित करने के लिए एक शेल का उपयोग करें।)

1
तो इसे इस तरह दो चरणों में करना (1) sudo -s(2) गूंज "# परीक्षण" >> /etc/pacman.conf काम करता है। लेकिन क्या एक ही लाइन में इसे निष्पादित करना संभव है?
केल्विन चेंग

15
sudo -s 'echo "# test" >>/etc/pacman.conf'यही मैं आपको बताने की कोशिश कर रहा हूं।
geekosaur

2
वास्तव में, मैंने कोशिश की कि आपके उत्तर को ऊपर पढ़ने के बाद, लेकिन इस तरह एक अजीब त्रुटि मिली: - sudo -s 'echo "# test" >> /etc/pacman.conf' /bin/bash: echo "# test" >> /etc/pacman.conf: No such file or directoryयही वजह है कि मैंने बाद में 2-चरण मैनुअल प्रक्रिया की कोशिश की।
केल्विन चेंग

16
आह ..... इस तरीके से एक आखिरी प्रयास -echo 'echo "# test" >> /etc/pacman.conf' | sudo -s
केल्विन चेंग

1
कैसे / कहां मुझे sudoकॉन्फ़िगरेशन अक्षम करने के बारे में पता चलता है -s? visudo?
केल्विन चेंग

127

जैसा कि @geekosaur ने बताया, शेल कमांड को चलाने से पहले पुनर्निर्देशन करता है। जब आप यह लिखें:

sudo foo >/some/file

आपकी वर्तमान शेल प्रक्रिया स्वयं की एक प्रतिलिपि बनाती है जो पहले /some/fileलिखने के लिए खोलने की कोशिश करती है , फिर उस फाइल को उसके मानक आउटपुट के लिए वर्णन करती है, और केवल उसे निष्पादित करती है sudo

यदि आपको अनुमति दी जाती है (sudoer कॉन्फ़िगर अक्सर चल रहे गोले को छोड़कर), तो आप इस तरह से कुछ कर सकते हैं:

sudo bash -c 'foo >/some/file'

लेकिन मुझे लगता है कि एक अच्छा समाधान सामान्य रूप | sudo teeसे >और | sudo tee -aइसके बजाय उपयोग करना है >>। यह विशेष रूप से उपयोगी है यदि पुनर्निर्देशन एकमात्र कारण है जो मुझे sudoपहले स्थान पर चाहिए; सब के बाद, रूट के रूप में अनावश्यक रूप से चलने वाली प्रक्रिया ठीक वही है जो sudoबचने के लिए बनाई गई थी। और echoजड़ के रूप में दौड़ना मूर्खतापूर्ण है।

echo '[archlinuxfr]' | sudo tee -a /etc/pacman.conf >/dev/null
echo 'Server = http://repo.archlinux.fr/$arch' | sudo tee -a /etc/pacman.conf >/dev/null
echo ' ' | sudo tee -a /etc/pacman.conf >/dev/null

मैंने > /dev/nullअंत में जोड़ा क्योंकि नामित फ़ाइल और अपने स्वयं के मानक आउटपुट दोनोंtee को इसका आउटपुट भेजता है , और मुझे इसे अपने टर्मिनल पर देखने की आवश्यकता नहीं है। ( कमांड एक भौतिक पाइपलाइन में एक "टी" कनेक्टर की तरह काम करता है, जहां यह इसका नाम हो जाता है।) और मैंने युगल ( ... ) के बजाय एकल उद्धरण ( ... ) पर स्विच किया ताकि सब कुछ शाब्दिक हो और मैं के सामने एक बैकस्लैश डाल करने के लिए नहीं था में । (उद्धरण या बैकलैश के बिना, शेल पैरामीटर के मूल्य द्वारा प्रतिस्थापित किया जाएगा , जो संभवतः मौजूद नहीं है, इस मामले में कुछ भी नहीं है और बस गायब हो जाता है।)tee''""$$arch$archarch$arch

ताकि रूट का उपयोग कर के रूप में फ़ाइलों को लिखने का ख्याल रखता है sudo। अब एक शेल स्क्रिप्ट में newline- युक्त टेक्स्ट आउटपुट करने के तरीकों पर एक लंबा विषयांतर। :)

BLUF के लिए, जैसा कि वे कहते हैं, मेरा पसंदीदा समाधान सिर्फ यहाँ एक दस्तावेज़ को उपरोक्त sudo teeकमांड में फीड करना होगा ; तो के लिए कोई ज़रूरत नहीं है catया echoया printfया बिल्कुल भी किसी अन्य आदेशों। एकल उद्धरण चिह्न प्रहरी परिचय में चले गए हैं <<'EOF', लेकिन उनका वहीं प्रभाव पड़ता है: शरीर को शाब्दिक पाठ के रूप में माना जाता है, इसलिए $archइसे अकेला छोड़ दिया जाता है:

sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch

EOF

लेकिन जब कि मैं यह कैसे करूँगा, वहाँ विकल्प हैं। यहाँ कुछ है:

आप echoप्रति पंक्ति एक के साथ छड़ी कर सकते हैं , लेकिन उन सभी को एक साथ एक उपधारा में समूहित कर सकते हैं, इसलिए आपको केवल एक बार फाइल में संलग्न करना होगा:

(echo '[archlinuxfr]'
 echo 'Server = http://repo.archlinux.fr/$arch'
 echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null

जोड़ते हैं -eकरने के लिए echo(और आप एक खोल है कि समर्थन करता है कि गैर POSIX एक्सटेंशन का उपयोग कर रहे हैं), नई-पंक्तियों सीधे स्ट्रिंग का उपयोग में एम्बेड कर सकते \n:

# NON-POSIX - NOT RECOMMENDED
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' | 
  sudo tee -a /etc/pacman.conf >/dev/null

लेकिन जैसा कि ऊपर कहा गया है, यह पॉसिक्स-निर्दिष्ट व्यवहार नहीं है; आपका खोल सिर्फ एक शाब्दिक प्रतिध्वनित हो सकता है -eजिसके \nबजाय एक स्ट्रिंग होती है जिसके बजाय शाब्दिक एस का एक गुच्छा होता है । ऐसा करने का POSIX तरीका printfइसके बजाय उपयोग करना है echo; यह स्वचालित रूप से अपने तर्क की तरह व्यवहार echo -eकरता है, लेकिन अंत में एक नई पंक्ति को स्वचालित रूप से संलग्न नहीं करता है, इसलिए आपको एक अतिरिक्त छड़ी करना \nहोगा, भी:

printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' | 
  sudo tee -a /etc/pacman.conf >/dev/null

उन समाधानों में से किसी के साथ, कमांड को एक तर्क स्ट्रिंग के रूप में जो मिलता है, उसमें दो-वर्ण अनुक्रम होता है \n, और यह कमांड प्रोग्राम पर ही निर्भर है (कोड के अंदर printfया अंदर echo) कि एक नई पंक्ति में अनुवाद करने के लिए। कई आधुनिक गोले में, आपके पास एएनएसआई उद्धरण का उपयोग करने का विकल्प होता है $'... ', जो कमांड प्रोग्राम को कभी भी स्ट्रिंग को देखने से पहले शाब्दिक न्यूलाइन्स \nमें अनुक्रमों का अनुवाद करेगा । इसका मतलब है कि इस तरह के तार किसी भी आदेश के साथ काम करते हैं, सादे पुराने सहित -less :-eecho

echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' | 
  sudo tee -a /etc/pacman.conf >/dev/null

लेकिन, की तुलना में अधिक पोर्टेबल है echo -e, ANSI उद्धरण अभी भी एक गैर POSIX एक्सटेंशन हैं।

और फिर, जबकि वे सभी विकल्प हैं, मैं tee <<EOFऊपर दिए गए सीधे समाधान को पसंद करता हूं ।


दिलचस्प! क्या आप फ़ाइल को / dev / null में फ़ाइल को चैंकाने का कारण बताते हुए एक नोट जोड़ सकते हैं?
22

sudo bash -c 'foo >/some/file'मेरे लिए osx पर काम करता है :-)
kayochin

मैं इस जवाब को पसंद करता हूं क्योंकि यह मल्टीलाइन टेक्स्ट के साथ काम करता है। cat <<EOF | sudo tee -a /some/file > /dev/null ...
ltvan

प्रभावी रूप से मेरा अंतिम उत्तर है, सिवाय इसके कि आपने एक बाहरी catप्रक्रिया को जोड़ा है। :)
मार्क रीड

17

http://www.innovationsts.com/blog/?p=2758

जैसा कि निर्देश हैं कि ऊपर स्पष्ट नहीं है मैं उस ब्लॉग पोस्ट के निर्देशों का उपयोग कर रहा हूं। उदाहरणों के साथ यह देखना आसान है कि आपको क्या करने की आवश्यकता है।

$ sudo cat /root/example.txt | gzip> /root/example.gz
-bash: /root/example.gz: अनुमति अस्वीकृत

ध्यान दें कि यह पाइप लाइन में दूसरा कमांड (gzip कमांड) है जो त्रुटि का कारण बनता है। यहीं -c विकल्प के साथ बैश का उपयोग करने की हमारी तकनीक आती है।

$ sudo bash -c 'cat /root/example.txt | gzip> /root/example.gz '
$ sudo ls /root/example.gz
/root/example.gz

हम ls कमांड के आउटपुट को देख सकते हैं कि संपीड़ित फ़ाइल निर्माण सफल हुआ।

दूसरी विधि पहले के समान है जिसमें हम कमांड स्ट्रिंग को बैश करने के लिए पास कर रहे हैं, लेकिन हम इसे sudo के माध्यम से पाइप लाइन में कर रहे हैं।

$ sudo rm /root/example.gz
$ echo "cat /root/example.t | | gzip> /root/example.gz" | sudo bash
$ sudo ls /root/example.gz
/root/example.gz


1
इस तरह के एक सरल आदेश के लिए, बैश के बजाय श का उपयोग करने के लिए थोड़ा बेहतर हो सकता है। जैसे sudo sh -c 'cat /root/example.txt | gzip> /root/example.gz '। लेकिन अन्यथा, अच्छा स्पष्टीकरण, +1।
bryce


1

चरण 1 बैश फ़ाइल में एक फ़ंक्शन बनाएँ ( write_pacman.sh)

#!/bin/bash

function write_pacman {
 tee -a /etc/pacman.conf > /dev/null << 'EOF'
  [archlinuxfr]
  Server = http://repo.archlinux.fr/\$arch
EOF
}

'EOF'$archचर की व्याख्या नहीं करेंगे ।

STE2 स्रोत बैश फ़ाइल

$ source write_pacman.sh

चरण 3 कार्य निष्पादित करें

$ write_pacman

EOF पर बोली किसके लिए है?
बिलबिला

0

फ़ाइलें संलग्न करें (sudo cat):

cat <origin-file> | sudo tee -a <target-file>

फ़ाइल करने के लिए गूँज (सुडो गूंज):

echo <origin> | sudo tee -a <target-file>

(EXTRA) ouput की अवहेलना करें:

echo >origin> | sudo tee -a <target-file> >/dev/null
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.