किसी फ़ाइल पर रीडायरेक्ट करना आपके पास अनुमति नहीं है


113

जब आप उस पर लिखने की अनुमति के बिना किसी फ़ाइल को संशोधित करने का प्रयास करते हैं, तो आपको एक त्रुटि मिलती है:

> touch /tmp/foo && sudo chown root /tmp/foo
> echo test > /tmp/foo
zsh: permission denied: /tmp/foo

सूदिंग मदद नहीं करता है, क्योंकि यह कमांड को रूट के रूप में चलाता है, लेकिन शेल स्टडआउट को रीडायरेक्ट करता है और जैसे ही आप फाइल को खोलता है:

> sudo echo test > /tmp/foo
zsh: permission denied: /tmp/foo

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

> sudo su
# echo test > /tmp/foo


कैसे आप अपने आप को tmp में बनाई गई फ़ाइल के लिए अनुमति नहीं दे सकते? क्या यह umask का becuase है?
k961

@ k961 मैं chownमालिक को बदलता था; यह सिर्फ एक उदाहरण था
माइकल Mrozek

जवाबों:


116

हाँ, का उपयोग कर tee। तो echo test > /tmp/fooबन जाता है

echo test | sudo tee /tmp/foo

आप भी संलग्न कर सकते हैं ( >>)

echo test | sudo tee -a /tmp/foo

27
टी स्टडआउट के लिए आउटपुट भी करेगा; कभी-कभी आप स्क्रीन को भरने वाली सामग्री नहीं चाहते हैं। इसे ठीक करने के लिए,echo test | sudo tee /tmp/foo > /dev/null
शॉन जे गौफ

आप इसे हेरेडोक के साथ कैसे करेंगे?
जॉनडोए

26

फ़ाइल के कंटेंट को बदलने के लिए echo( >शेल रिडायरेक्शन ऑपरेटर की तरह)।

echo test | sudo dd of=/tmp/foo

फ़ाइल में लिखने के लिए (शुरुआत में, हालांकि आप seekअलग-अलग ऑफ़सेट में आउटपुट का उपयोग कर सकते हैं ) बिना ट्रंकिंग ( 1<>बॉर्न शेल ऑपरेटर की तरह):

echo test | sudo dd of=/tmp/foo conv=notrunc

>>GNU के साथ फ़ाइल (जैसे ) में संलग्न करने के लिए dd:

echo test | sudo dd of=/tmp/foo oflag=append conv=notrunc

यह भी देखें जीएनयू ddके conv=exclकिसी मौजूदा फ़ाइल (साथ की तरह clobbering से बचने के लिए set -o noclobberPOSIX गोले में) और conv=nocreatविपरीत के लिए (केवल किसी मौजूदा फ़ाइल को अद्यतन)।


चालाक! यह echo test | sudo tee /tmp/foo >/dev/nullआउटपुट को छोड़ने के लिए करने की आवश्यकता को कम करता है ।
एडम काटज़

2
मुझे वह वापस लेना पड़ सकता है; ddइसके लिए अविश्वसनीय है जब तक कि आप अस्पष्ट GNU- केवल विकल्पों का उपयोग नहीं कर रहे हैं iflag=fullblock oflag=fullblock, जो इस उत्तर की लालित्य को दूर करते हैं। मैं साथ रहूँगा tee
एडम काटज़

5
dd गैर-अस्पष्ट bs = 1
umeboshi

2
@umeboshi लेकिन केवल तभी विश्वसनीय हो जब आपको यह जानने के लिए पर्याप्त अनुभव हो कि आप क्या कर रहे हैं। के लिए ddकाफी खतरनाक हो सकता है (यदि नहीं कहना है: विनाशकारी) अगर केवल थोड़ी सी गलती की गई थी। इसलिए नए उपयोगकर्ताओं के लिए, मैं इसके बजाय teeसुरक्षित किनारे पर होने की विधि की सलाह दूंगा।
वाक्यविन्यास

1
@AdamKatz, dd of=fileअकेले ( count/ / skip) के मामले में , यह विश्वसनीय है। iflag=fullblockजरूरत नहीं है क्योंकि यहां ddआउटपुट पर लिखते हैं कि यह इनपुट पर क्या पढ़ा है। इससे कोई फर्क नहीं पड़ता कि यह पूर्ण ब्लॉक नहीं था।
स्टीफन चेजलस

12

tee शायद सबसे अच्छा विकल्प है, लेकिन आपकी स्थिति के आधार पर कुछ इस तरह से पर्याप्त हो सकता है:

sudo sh -c 'echo test > /tmp/foo'

1
3 समस्याएं: evalएक साधारण के बजाय sh -c; -आई, जो आपके कामकाजी डायर को बदल देगा; पूरे कमांड को रूट के रूप में चलाना, जो बदल सकता है यह व्यवहार है या एक अनावश्यक जोखिम का परिचय दे सकता है। ऐसा क्यों हुआ?

4
आपने नहीं किया, लेकिन यह भ्रामक है, आमतौर पर बुरा और शायद खतरनाक भी।

5

जबकि मैं सहमत हूँ, कि | sudo teeविहित तरीका है, कभी-कभी sed (यहाँ GNU मानकर sed) काम हो सकता है:

cat sudotest 
line 1

sudo sed -i '1iitest' sudotest && cat sudotest 
itest
line 1

sudo sed -i '$aatest' sudotest && cat sudotest 
itest
line 1
atest

-iजगह में फ़ाइल को संशोधित करता है। 1iमतलब लाइन 1 से पहले इन्सर्ट करें$aमतलब आखिरी लाइन के बाद अपेंड करें

या कॉपी करने के लिए xclipboard:

somecommand | xclip
sudo gedit sudotest
move cursor to desired place, click middle mouse button to insert, save

1
यह एक प्राचीन चीनी पहेली जैसा शब्द है। यह समझने की कोशिश नहीं की जा सकती है कि यह कितने उत्थान को मिला है। ( hrmph )
वाक्यविन्यास

1
@ साइनाटैक्सेरोर: सर, मुझे क्षमा करें, मैं एक देशी अंग्रेजी वक्ता नहीं हूं। यदि आप निर्दिष्ट करते हैं कि आपके लिए क्या अस्पष्ट है, तो मैं अपने उत्तर को बेहतर बनाने की कोशिश कर सकता था। गर्ट के लिए 65 अपवोट्स की तुलना में, 4 नहीं लगता है कि कई अपवोट्स, या तो, आपको नहीं लगता?
उपयोगकर्ता अज्ञात

वैसे मैं 4: -D से बहुत संतुष्ट हूँ। आपकी अंग्रेजी बिल्कुल भी खराब नहीं है। यह सिर्फ एक तरह के शब्द है, जिसमें एक प्रकार का टेरी नर्डस्पेक है। मुझे लगता है कि आप एक कोडर रहे हैं चाहिए। एक-दूसरे के बीच कोडर खुद को इस तरह से पूरी तरह से समझेंगे, लेकिन एक गैर-कोडर को यह सोचना चाहिए कि यह शब्द जैसा है ... जैसा कि कहा गया है।
वाक्यविन्यास

ध्यान दें कि sed -iवास्तव में फ़ाइल को जगह में संशोधित नहीं करता है - यह एक अस्थायी फ़ाइल बनाता है और इसे बाहर निकलने पर नाम देता है। इसलिए आप tail -f ...मूल फ़ाइल पर ऐसा कुछ नहीं कर पाएंगे और sed -i ...पाइपलाइन चलाने के दौरान आउटपुट का उपयोग करके देख सकते हैं
एंड्रयू हेनले

@AndrewHenle: हां, चूँकि आकार में वृद्धि या सिकुड़न हो सकती है, और चूँकि शायद सबसे अधिक sed चालान के मामले में है, और आप भी नहीं कर सकते हैं - afaik - SSDs पर एक ही स्थान पर लिखें, यह केवल एक 'छद्म स्थान' ऑपरेशन है । एक गैर देशी अंग्रेजी बोलने वाले के रूप में, क्या मैं एक संक्षिप्त अभिव्यक्ति के लिए पूछ सकता हूं, जिसकी इतनी गलत व्याख्या नहीं की गई है? बस -i creates a new file of same nameया कुछ और कॉम्पैक्ट है? मुझे लगता है मुझे पसंद है in place, क्योंकि यह बताते हैं i। ग्नू-सेड मैनपेज इसे जगह में भी कहते हैं और लंबा झंडा है --in-place
उपयोगकर्ता अज्ञात

2

मैं एक समान समस्या के लिए अपने दिमाग के विचारों के पीछे की ओर घूम रहा हूं, और निम्नलिखित समाधानों के साथ आया हूं:

  • sudo uncatजहां uncatएक प्रोग्राम है जो मानक इनपुट पढ़ता है और इसे कमांड लाइन पर नामित फ़ाइल में लिखता है, लेकिन मैंने uncatअभी तक नहीं लिखा है।

  • sudocatउस के संस्करण sudoeditमैंने अभी तक नहीं लिखा है कि एक क्लीनर sudo catया करता है sudo uncat

  • या sudoeditEDITOR के साथ प्रयोग करने की यह छोटी सी तरकीब जो एक शेल स्क्रिप्ट है

    #!/bin/sh
    # uncat
    cat > "$1"

    जिसे |sudo ./uncat fileया तो आह्वान किया जा सकता है, | EDITOR=./uncat sudoeditलेकिन इसके रोचक दुष्परिणाम हैं।


catचुनाव के लिए फ़ाइलों की एक सूची लेता है बिल्ली inate, इसलिए uncat लिए फ़ाइलों की एक सूची ले जाना चाहिए संयुक्त राष्ट्र चोर बिल्ली को inate। प्रत्येक फ़ाइल में कितना डालना है, यह तय करने के लिए जादू का उपयोग करना होगा। वैकल्पिक नाम शामिल dog, to-file, redirect
ctrl-alt-delor

मैं किसी भी कारण के बारे में नहीं सोच सकता कि मैं क्यों चाहता uncatहूं tee
वाइल्डकार्ड

1
अच्छी तरह से, teeतुच्छ दोष यह है कि वह अपने स्टडआउट को अपने स्टड को लिखता है - जो कि स्ट्रेटआउट को पुनर्निर्देशित करके तुच्छ रूप से कम किया जाता है /dev/null। अन्य विकल्पों में शामिल हैं dd of=/tmp/foo(एक अन्य उत्तर में उल्लेख किया गया है), जो स्टेटडर को स्थिति की जानकारी लिखता है, और cp /dev/stdin /tmp/foo
स्कॉट

1

स्पॉन्डिल पैकेज से स्पंज का उपयोग करें। इसका यह फायदा है कि यह स्टडआउट को नहीं लिखता है।

echo test | sudo sponge /tmp/foo

इसे अधिलेखित करने के बजाय फ़ाइल में संलग्न करने के लिए -a विकल्प का उपयोग करें।


1
मुझे यकीन नहीं है कि स्टडआउट प्रस्तुत करने के लिए लिखने का क्या फायदा है, लेकिन आप आउटपुट को पुनर्निर्देशित कर सकते हैं /dev/nullयदि यह एक मुद्दा था
माइकल Mrozek

1
बेशक मैं / dev / null को रीडायरेक्ट कर सकता हूं, लेकिन रीडायरेक्शन के बिना कमांड पढ़ना और टाइप करना आसान है। स्टडआउट न लिखने का फायदा यह है कि मेरा टर्मिनल खचाखच भरा नहीं है।
होन्ताव्री लेवेंटे

1
मैं पुनर्निर्देशन को छोड़ने के लिए पैकेज स्थापित नहीं करूंगा, लेकिन मैं नियमित रूप से स्पंज का उपयोग करता हूं, इसलिए यह पहले से ही है।
होन्तेवरी लेवेंट

0

त्रुटि उस क्रम से आती है जिसमें शेल चीजों को करता है।

रीडायरेक्शन को शेल द्वारा निष्पादित होने से पहले ही नियंत्रित किया जाता है sudo, और इसलिए उपयोगकर्ता की अनुमति के साथ किया जाता है जिसे आप वर्तमान में काम कर रहे हैं। चूँकि आपके पास रीडायरेक्शन के लक्ष्य को बनाने / छिन्न-भिन्न करने की अनुमति नहीं है, इसलिए आपको permission deniedशेल से एक त्रुटि मिलती है ।

समाधान की गारंटी यह है कि आउटपुट फ़ाइल आपके द्वारा दी गई पहचान के तहत बनाई गई है sudo, जैसे tee:

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