जिस स्थान पर मुझे लिखने की अनुमति नहीं है, वहां मैं आउटपुट को रीडायरेक्ट करने के लिए sudo का उपयोग कैसे करूं?


881

मुझे हमारे एक विकास RedHat linux बॉक्स में sudo एक्सेस दिया गया है, और मुझे लगता है कि मैं अपने आप को अक्सर एक ऐसे स्थान पर पुनः निर्देशित करने की आवश्यकता करता हूँ, जहाँ मुझे आम तौर पर लिखने की पहुँच नहीं है।

परेशानी यह है, यह आकस्मिक उदाहरण काम नहीं करता है:

sudo ls -hal /root/ > /root/test.out

मैं सिर्फ प्रतिक्रिया प्राप्त करता हूं:

-bash: /root/test.out: Permission denied

में इससे कैसे चला सकता हूँ?


1
chmod u + w filename का उपयोग करें
Szabolcs Dombi

@DombiSzabolcs आप सुझाव दे रहे हैं कि मैं फ़ाइल को पहले sudo के रूप में बनाता हूं, फिर खुद को अनुमति दें? अच्छा विचार।
जोनाथन

कई स्थितियों में आप यहाँ समाप्त होते हैं क्योंकि आपने पूछा था "मुझे अनुमति से इनकार क्यों करना है?" कभी-कभी उत्तर यह होता है कि आपको फ़ाइल बनाने की आवश्यकता होती है root(जिस स्थिति में उत्तर पढ़ने के लिए आगे बढ़ते हैं) लेकिन बहुत बार, आपको बस फ़ाइल को कहीं और बनाने की आवश्यकता होती है, जैसे कि स्वयं।
ट्रिपलए

1
इन उत्तरों के साथ संघर्ष करने के बाद, मैं आखिरकार एक अस्थायी फ़ाइल पर रीडायरेक्ट करना चाहता हूं और सूडो इसे गंतव्य तक ले जाते हैं।
टिंगकियन एलआई

यह भी देखें stackoverflow.com/questions/84882/…
Nate Eldredge

जवाबों:


1232

आपकी कमांड काम नहीं करती है क्योंकि पुनर्निर्देशन आपके शेल द्वारा किया जाता है जिसे लिखने की अनुमति नहीं है /root/test.out। आउटपुट का पुनर्निर्देशन sudo द्वारा नहीं किया जाता है।

कई समाधान हैं:

  • सुडोल के साथ एक शेल चलाएं और -cविकल्प का उपयोग करके इसे कमांड दें :

    sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • अपने आदेशों के साथ एक स्क्रिप्ट बनाएं और सूडो के साथ उस स्क्रिप्ट को चलाएं:

    #!/bin/sh
    ls -hal /root/ > /root/test.out
    

    भागो sudo ls.sh। यदि आप एक अस्थायी फ़ाइल नहीं बनाना चाहते हैं तो स्टीव बेनेट का उत्तर देखें ।

  • इसके साथ एक शेल लॉन्च करें, sudo -sफिर अपनी कमांड चलाएं:

    [nobody@so]$ sudo -s
    [root@so]# ls -hal /root/ > /root/test.out
    [root@so]# ^D
    [nobody@so]$
    
  • उपयोग करें sudo tee(यदि आपको -cविकल्प का उपयोग करते समय बहुत अधिक बचना है ):

    sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
    

    स्क्रीन पर आउटपुट से टी/dev/null को रोकने के लिए रीडायरेक्ट की आवश्यकता होती है । करने के लिए संलग्न के बजाय आउटपुट फ़ाइल (अधिलेखन की ), उपयोग या (पिछले एक के लिए विशिष्ट है GNU coreutils )।>>tee -atee --append

दूसरे, तीसरे और चौथे समाधान के लिए जेडी , एडम जे। फोस्टर और जॉनाथन के लिए धन्यवाद ।


1
एक शानदार जवाब है जो आपको बताता है कि कैसे STDERR और STDOUT को अलग से रीडायरेक्ट करना है: stackoverflow.com/questions/692000/… ... मूल रूप सेperl -e 'print "STDIN\n"; print STDERR "STDERR\n"; ' > >( tee stdout.log ) 2> >( tee stderr.log >&2 )
misant.info

2
आप शेल्ड आउट कमांड में चर का उपयोग करने के लिए 'sudo -E ...' करना चाहते हैं (उदाहरण के लिए, स्क्रिप्ट में इसका उपयोग करते समय)।
उरिखीदुर

3
टी / आउटपुट को / dev / null में रीडायरेक्ट करना शायद बहुत से मामलों में आवश्यक नहीं है जहाँ आउटपुट को स्क्रीन पर गूँजना हानिरहित है। उदाहरण के लिए, जब नियमित कमांड या छोटे पाठ फ़ाइलों की सामग्री के आउटपुट के साथ काम करते हैं।
थोमसट्रेटर

105

यहाँ किसी ने सिर्फ सुझाव दिया है:

sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null

इसका उपयोग किसी भी कमांड को रीडायरेक्ट करने के लिए भी किया जा सकता है, एक ऐसी डायरेक्टरी के लिए जिसका आपको एक्सेस नहीं है। यह काम करता है क्योंकि टी कार्यक्रम प्रभावी रूप से एक "एक फ़ाइल के लिए गूंज" कार्यक्रम है, और इसे ऊपर बताए गए मूल उदाहरण के समान रखने के लिए स्क्रीन पर आउटपुट करने से रोकने के लिए / dev / null को पुनर्निर्देशित करना भी है।


5
कई मामलों में, अर्थात् यदि सामान्य उपयोगकर्ता के पास कमांड करने के लिए प्रमिशन है और "केवल" वांछित आउटपुट फाइल को नहीं लिख सकता है, तो पहली sudo(यानी, कमांड के लिए) को छोड़ा जा सकता है
Hagen von Eitzen

81

एक तरकीब मैंने खुद निकाली

sudo ls -hal /root/ | sudo dd of=/root/test.out

16
sudo ddsudo tee /root/file > /dev/nullऊपर दिए गए उदाहरणों से बेहतर है !
क्रिश्चियनम

14
dd कोई अजीब अस्पष्ट आदेश नहीं है। जब भी आपको दो ब्लॉक डिवाइस के बीच बफरिंग के साथ बड़ी मात्रा में डेटा कॉपी करने की आवश्यकता होती है तो इसका उपयोग किया जाता है। वाक्यविन्यास वास्तव में बहुत सरल है, ddकमांड नाम है, of=/root/test.outयह तर्क है जो बताता है ddकि आउटपुट फाइल क्या है।
रैलि

14
@ चेस्ट एवरीथिंग 'अस्पष्ट' है जब तक आप यह नहीं सीखते कि यह क्या है। आउटपुट फाइल काof मतलब है और लिनक्स और ओएसएक्स दोनों में उपयोग किया जाने वाला एक बहुत लोकप्रिय उपकरण है (ज्यादातर डिस्क्स के लिए चित्र लिखने के लिए)। यह सुनिश्चित करने के लिए एक साफ चाल है। dd
ब्लॉकलूप

12
ddशायद teeयहाँ भी उतना ही उपयोगी है। दोनों ही मामलों में आप एक सामान्य, अच्छी तरह से ज्ञात आदेश का उपयोग कर रहे हैं, जबकि अपने मूल उद्देश्य से थोड़ा अलग है, फिर भी अच्छी तरह से जाना जाता है और अच्छी तरह से प्रलेखित है। हालांकि ddभारी मात्रा में डेटा की नकल करना अच्छा है, यह छोटी मात्रा के साथ चूसना नहीं करता है। इसका लाभ यह है कि आउटपुट को मानक आउटपुट पर भी नहीं गूँजते।
थोमसट्रेटर

26
जब भी आप sudo ddएक दूसरे के बगल में शब्द लिखते हैं , तो आप बहुत, बहुत सुनिश्चित करना चाहते हैं कि जो तर्क का पालन करते हैं वे सही हैं (विशेष रूप से इसके गैर-मानक वाक्यविन्यास पर विचार करते हुए)। वे इसे कुछ भी नहीं के लिए "डिस्क विध्वंसक" नहीं कहते हैं ...
एलि_म

45

समस्या यह है कि कमांड के तहत चला जाता है sudo, लेकिन पुनर्निर्देशन आपके उपयोगकर्ता के तहत चलाया जाता है। यह शेल द्वारा किया जाता है और इसके बारे में बहुत कम आप कर सकते हैं।

sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection

इसे दरकिनार करने के सामान्य तरीके हैं:

  • एक स्क्रिप्ट में कमांड लपेटें जिसे आप सूडो के तहत कहते हैं।

    यदि कमांड और / या लॉग फाइल में बदलाव होता है, तो आप स्क्रिप्ट को तर्क के रूप में ले सकते हैं। उदाहरण के लिए:

    sudo log_script command /log/file.txt
    
  • शेल को कॉल करें और कमांड लाइन को एक पैरामीटर के रूप में पास करें -c

    यह एक बंद कंपाउंड कमांड के लिए विशेष रूप से उपयोगी है। उदाहरण के लिए:

    sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
    

23

विषय पर एक और बदलाव:

sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF

या बेशक:

echo 'ls -hal /root/ > /root/test.out' | sudo bash

उनके पास (छोटे) लाभ हैं जिन्हें आपको / sudoया किसी भी तर्क को याद रखने की आवश्यकता नहीं हैshbash


18

क्यों टी विकल्प बेहतर है पर थोड़ा स्पष्ट करना

यह मानते हुए कि आउटपुट बनाने वाली कमांड को निष्पादित करने के लिए आपके पास उपयुक्त अनुमति है, यदि आप अपने कमांड के आउटपुट को टी करने के लिए पाइप करते हैं, तो आपको प्रश्न में फ़ाइल को लिखने (या अपेंड) करने के लिए sudo और डायरेक्ट टी के साथ टी के प्राइवेटबिल्ड को ऊंचा करना होगा।

प्रश्न में दिए गए उदाहरण में इसका अर्थ होगा:

ls -hal /root/ | sudo tee /root/test.out

कुछ और व्यावहारिक उदाहरणों के लिए:

# kill off one source of annoying advertisements
echo 127.0.0.1 ad.doubleclick.net | sudo tee -a /etc/hosts

# configure eth4 to come up on boot, set IP and netmask (centos 6.4)
echo -e "ONBOOT=\"YES\"\nIPADDR=10.42.84.168\nPREFIX=24" | sudo tee -a /etc/sysconfig/network-scripts/ifcfg-eth4

इन उदाहरणों में से प्रत्येक में आप एक गैर-विशेषाधिकार प्राप्त कमांड का आउटपुट ले रहे हैं और एक फाइल पर लिख रहे हैं जो आमतौर पर केवल रूट द्वारा लिखने योग्य है, जो आपके प्रश्न का मूल है।

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

ध्यान दें कि आप इसे (जैसे >>) को अधिलेखित करने के बजाय लक्ष्य फ़ाइल में एपेंड (जैसे ) को जोड़ने के लिए -a विकल्प का उपयोग कर सकते हैं >


क्षमा करें js3, लेकिन यह पहले से ही (2008 में वापस) सुझाव दिया गया है और दूसरा सर्वोच्च जवाब पर बैठी है: stackoverflow.com/a/82553/6910
जोनाथन

2
आप सही हैं, जोनाथन, मैं उन कारणों पर विस्तार करने के लिए अपने उत्तर को अपडेट करूंगा कि यह एक बेहतर विकल्प क्यों है। उपयोगी प्रतिक्रिया के लिए धन्यवाद।
jg3

17

सुडोल बनाओ एक खोल, इस तरह से:

sudo sh -c "echo foo > ~root/out"

11

जिस तरह से मैं इस मुद्दे के बारे में जाना जाएगा:

यदि आपको फ़ाइल लिखने / बदलने की आवश्यकता है:

echo "some text" | sudo tee /path/to/file

यदि आपको फ़ाइल में संलग्न करना है:

echo "some text" | sudo tee -a /path/to/file

1
उपरोक्त उत्तर के लिए यह पर्याप्त रूप से भिन्न कैसे है?
जोनाथन

2
यह "काफी हद तक अलग नहीं है" लेकिन यह फ़ाइल को बदलने और जोड़ने के बीच विशिष्ट उपयोग को स्पष्ट करता है।
जमादग्नि

1
यह वह जवाब है जो मैंने अपनी चीट शीट पर कॉपी किया है।
मोर्टिमरकैट

5

स्क्रिप्ट लिखने के बारे में कैसे?

फ़ाइल नाम: myscript

#!/bin/sh

/bin/ls -lah /root > /root/test.out

# end script

फिर स्क्रिप्ट चलाने के लिए sudo का उपयोग करें:

sudo ./myscript

4

जब भी मुझे कुछ ऐसा करना होता है तो मैं बस जड़ हो जाता हूं:

# sudo -s
# ls -hal /root/ > /root/test.out
# exit

यह शायद सबसे अच्छा तरीका नहीं है, लेकिन यह काम करता है।


4

मैं इसे इस तरह से करूंगा:

sudo su -c 'ls -hal /root/ > /root/test.out'

2
यह वास्तव में थोड़ा साफ लगता है, क्योंकि आपको शेल को स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता नहीं है।
स्टीव बेनेट

1
एक छोटी सी खामी यह है कि यह एक अतिरिक्त प्रक्रिया ( su) $ sudo su -c 'pstree -sp $$ >/dev/fd/1' init(1)───gnome-terminal(6880)───bash(6945)───sudo(401)───su(402)───bash(410)───pstree(411)
चलाती है

3

एक मरे हुए घोड़े को मारने का मतलब नहीं है, लेकिन यहां बहुत सारे जवाब हैं जो उपयोग करते हैं tee, जिसका अर्थ है कि आपको पुनर्निर्देशित stdoutकरना होगा /dev/nullजब तक आप स्क्रीन पर एक प्रति नहीं देखना चाहते।

एक सरल समाधान catइस तरह से उपयोग करना है:

sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"

ध्यान दें कि पुनर्निर्देशन को उद्धरणों के अंदर कैसे डाला जाता है ताकि इसे sudoचलाने वाले के बजाय शुरू किए गए शेल द्वारा मूल्यांकन किया जाए।


यह ठीक काम करता है। मुझे समझ नहीं आता कि यह एक नकारात्मक वोट क्यों था। Upvoted।
तैमू लीस्ती

4
मुझे लगता है कि इसे बहुत प्यार नहीं मिला क्योंकि यह इससे बेहतर नहीं है sudo bash -c "ls -hal /root > /root/test.out"। टी का उपयोग करने से एक शेल की जरूरत से बचा जाता है, जबकि बिल्ली नहीं होती है।
निक रूसो

2

यह शामिल जवाब पर आधारित है tee। चीजों को आसान बनाने के लिए मैंने एक छोटी स्क्रिप्ट लिखी (मैं इसे कॉल करता हूं suwrite) और इसे अनुमति के /usr/local/bin/साथ रखा +x:

#! /bin/sh
if [ $# = 0 ] ; then
    echo "USAGE: <command writing to stdout> | suwrite [-a] <output file 1> ..." >&2
    exit 1
fi
for arg in "$@" ; do
    if [ ${arg#/dev/} != ${arg} ] ; then
        echo "Found dangerous argument ‘$arg’. Will exit."
        exit 2
    fi
done
sudo tee "$@" > /dev/null

जैसा कि कोड में USAGE में दिखाया गया है , आपको बस इतना करना है कि इस स्क्रिप्ट के आउटपुट को वांछित सुपरसुसर-सुलभ फ़ाइल नाम के बाद पाइप करना है और यह ज़रूरत पड़ने पर स्वचालित रूप से आपके पासवर्ड के लिए संकेत देगा sudo

echo test | suwrite /root/test.txt

ध्यान दें कि चूंकि यह एक साधारण आवरण है tee, इसलिए यह टी -aको जोड़ने के विकल्प को भी स्वीकार करेगा , और एक ही समय में कई फ़ाइलों को लिखने का समर्थन भी करता है।

echo test2 | suwrite -a /root/test.txt
echo test-multi | suwrite /root/test-a.txt /root/test-b.txt

इसके पास /dev/उपकरणों को लिखने के खिलाफ कुछ सरलीकृत संरक्षण है जो इस पृष्ठ पर टिप्पणियों में से एक में वर्णित एक चिंता थी।


1

हो सकता है कि आपको केवल कुछ कार्यक्रमों / रास्तों के लिए सूडो एक्सेस दिया गया हो? फिर आप जो चाहते हैं वह करने का कोई तरीका नहीं है। (जब तक आप इसे किसी तरह हैक नहीं करेंगे)

अगर ऐसा नहीं है तो हो सकता है कि आप बैश स्क्रिप्ट लिख सकें:

cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out 

प्रेस ctrl+ d:

chmod a+x myscript.sh
sudo myscript.sh

आशा है कि यह मदद करेगा।


1
sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  

1
यदि आपके पास sudoवैसे भी atउपयोगी या आवश्यक नहीं है। sudo sh -c 'echo test >/tmp/test.out'वही अधिक कुशलता से और सुरुचिपूर्ण ढंग से करता है (लेकिन अभी भी इस दोष से ग्रस्त है कि आप शायद ऐसी चीजें चला रहे हैं rootजो उस विशेषाधिकार को नहीं करते हैं; आपको आम तौर पर विशेषाधिकार प्राप्त कमांड से बचना चाहिए जब आप कर सकते हैं)।
ट्रिपल जू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.