Çıkışı yazma iznim olmayan bir konuma yönlendirmek için sudo'yu nasıl kullanabilirim?


881

Geliştirme RedHat linux kutularımızdan birine sudo erişimi verildi ve kendimi genellikle çıktıları normalde yazma erişimim olmayan bir konuma yönlendirmeye ihtiyaç duyduğumu görüyorum.

Sorun şu ki, bu çelişkili örnek işe yaramıyor:

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

Sadece cevabı alıyorum:

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

Bunu nasıl çalıştırabilirim?


1
chmod u + w dosya
adını kullan

@DombiSzabolcs Dosyayı önce sudo olarak oluşturmamı, sonra kendime izin vermemi mi öneriyorsunuz? İyi bir fikir.
Jonathan

Birçok durumda, "Neden izin verilmiyor?" Bazen cevap, bir dosyayı root(bu durumda cevapları okumaya devam edin) olarak oluşturmanız gerektiğidir, ancak çoğu zaman, dosyayı kendiniz gibi başka bir yerde oluşturmanız gerekir.
tripleee

1
Bu cevaplarla uğraştıktan sonra nihayet bir geçici dosyaya yönlendirmeyi ve sudo'yu hedefe taşımayı seçtim.
TingQian LI

Yanıtlar:


1233

Yeniden yönlendirme, yazma iznine sahip olmayan kabuğunuz tarafından gerçekleştirildiğinden komutunuz çalışmıyor /root/test.out. Çıkış yönlendirme değildir Sudo tarafından gerçekleştirilir.

Birden fazla çözüm var:

  • Sudo ile bir kabuk çalıştırın ve şu komutu kullanarak komutu verin -c:

    sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • Komutlarınızla bir komut dosyası oluşturun ve bu komut dosyasını sudo ile çalıştırın:

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

    Koş sudo ls.sh. Geçici bir dosya oluşturmak istemiyorsanız Steve Bennett'in cevabına bakınız .

  • Bir kabuk başlatın sudo -sve komutlarınızı çalıştırın:

    [nobody@so]$ sudo -s
    [root@so]# ls -hal /root/ > /root/test.out
    [root@so]# ^D
    [nobody@so]$
    
  • Kullanım sudo tee( -cseçeneği kullanırken çok fazla kaçmanız gerekiyorsa ):

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

    Te yönlendirmesinin ekrana /dev/nullçıkmasını durdurmak için yönlendirme gereklidir . To ekleme yerine çıktı dosyası (yazılmadan ), kullanımını veya (sonuncusu özgüdür GNU coreutils ).>>tee -atee --append

İkinci, üçüncü ve dördüncü çözümler için Jd , Adam J. Forster ve Johnathan'a teşekkürler .


1
STDERR ve perl -e 'print "STDIN\n"; print STDERR "STDERR\n"; ' > >( tee stdout.log ) 2> >( tee stderr.log >&2 )
STDOUT'u

2
Shelled out komutundaki değişkenleri kullanmak için 'sudo -E ...' yapmak isteyeceksiniz (örneğin bunu bir komut dosyasında kullanırken).
Urhixidur

3
Te çıkışının / dev / null değerine yeniden yönlendirilmesi, çıktının ekrana yansıtılmasının zararsız olduğu birçok durumda muhtemelen gerekli değildir. Örneğin, yalnızca normal komutların çıktısı veya küçük metin dosyalarının içeriği ile uğraşırken.
thomasrutter

105

Buradaki biri sadece sudoing tee önerdi:

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

Bu, herhangi bir komutu, erişiminiz olmayan bir dizine yeniden yönlendirmek için de kullanılabilir. Tee programı etkili bir şekilde "bir dosyaya yankı" programı olduğu için çalışır ve / dev / null yönlendirme, yukarıdaki orijinal örnekle aynı tutmak için ekrana çıkmasını durdurmaktır.


5
Çoğu durumda, normal kullanıcının komutu yerine getirmesi için önermeleri varsa ve "yalnızca" istenen çıktı dosyasına yazamazsa, ilk sudo(yani komutun kendisi için) atlanabilir
Hagen von Eitzen

81

Kendimi anladığım bir numara

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

16
sudo ddsudo tee /root/file > /dev/nullyukarıdaki örneklerden daha iyidir !
kristianlm

14
gg tuhaf bir karanlık komut değildir. İki blok cihaz arasında arabelleğe alma yoluyla büyük miktarda veri kopyalamanız gerektiğinde kullanılır. Sözdizimi aslında oldukça basit, ddkomut adı, Çıktı Dosyalarının ne of=/root/test.outolduğunu söyleyen argüman dd.
rhlee

14
@steve Ne olduğunu öğrenene kadar her şey 'belirsiz'. çıktı dosyasıof anlamına gelir ve hem Linux hem de OSX'te kullanılan çok popüler bir araçtır (çoğunlukla disklere görüntü yazmak için). Bu kesinlikle düzgün bir numara. dd
blockloop

12
ddmuhtemelen teeburada olduğu gibi eşit derecede faydalıdır . Her iki durumda da, orijinal amaçlanandan biraz farklı olsa da, hala iyi bilinen ve iyi belgelenmiş bir amaç için ortak, iyi bilinen bir komut kullanıyorsunuz. ddBüyük miktarlardaki verileri kopyalamakta iyi olsa da , küçük miktarlarda emilmez. Burada çıktıyı standart çıktıya da yansıtmama avantajı vardır.
thomasrutter

26
Yan yana sözcükler yazdığınızda, aşağıdaki bağımsız değişkenlerin doğru olduğundan (özellikle standart dışı sözdizimi dikkate alındığında) sudo ddçok, çok emin olmak istersiniz . Hiçbir şey için "disk yok edici"
demiyorlar

45

Sorun, komutun altında çalıştırılması sudo, ancak yönlendirmenin kullanıcı altında çalıştırılmasıdır. Bu kabuk tarafından yapılır ve bu konuda yapabileceğiniz çok az şey vardır.

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

Bunu atlamanın olağan yolları:

  • Komutları sudo altında çağırdığınız bir komut dosyasına sarın.

    Komutlar ve / veya günlük dosyası değişirse, komut dosyasının bunları bağımsız değişken olarak almasını sağlayabilirsiniz. Örneğin:

    sudo log_script command /log/file.txt
    
  • Bir kabuk çağırın ve komut satırını parametre olarak -c

    Bu özellikle bir defaya mahsus bileşik komutlar için kullanışlıdır. Örneğin:

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

23

Tema ile ilgili başka bir varyasyon:

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

Veya tabii ki:

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

Herhangi bir argümanı sudoveya sh/ veyabash


18

Tee seçeneğinin neden tercih edildiğine dair biraz açıklama

Çıktıyı oluşturan komutu yürütmek için uygun izniniz olduğunu varsayarsak, komutunuzun çıktısını tee'ye bağlarsanız, söz konusu dosyaya yazmak (veya eklemek) için tee'nin ayrıcalıklarını sudo ve direct tee ile yükseltmeniz yeterlidir.

soruda verilen örnekte şu anlama gelir:

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

birkaç pratik örnek için:

# 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

Bu örneklerin her birinde ayrıcalıklı olmayan bir komutun çıktısını alıyorsunuz ve genellikle sorunun kaynağı olan kök tarafından yazılabilen bir dosyaya yazıyorsunuz.

Çıkışı üreten komut yükseltilmiş ayrıcalıklarla yürütülmediğinden, bu şekilde yapmak iyi bir fikirdir. Burada önemli değil, echoancak source komutu tamamen güvenmediğiniz bir komut dosyası olduğunda, bu çok önemlidir.

>>Hedef dosyanın üzerine yazmak (gibi ) eklemek (gibi ) eklemek için -a seçeneğini kullanabilirsiniz >.


Üzgünüz js3, ama bu zaten önerildi (2008'de geri döndü) ve en yüksek ikinci cevapta oturuyor: stackoverflow.com/a/82553/6910
Jonathan

2
Haklısın Jonathan, bunun tercih edilen bir seçenek olmasının nedenlerini genişletmek için cevabımı güncelleyeceğim. Yardımcı geri bildiriminiz için teşekkürler.
jg3

17

Sudo'nun bir kabuk çalıştırmasını sağlayın, şöyle:

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

11

Bu sorunla ilgili olarak:

Dosyayı yazmanız / değiştirmeniz gerekiyorsa:

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

Dosyaya eklemeniz gerekiyorsa:

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

1
Bu yukarıdaki cevaplardan önemli ölçüde farklı mı?
Jonathan

2
"Oldukça farklı" değildir, ancak dosyayı değiştirme ve dosyaya ekleme arasındaki ayırt edici kullanımı netleştirir.
jamadagni

1
Bu, kopya kağıdıma kopyaladığım cevap.
MortimerCat

5

Senaryo yazmaya ne dersin?

Dosyaadı: myscript

#!/bin/sh

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

# end script

Sonra komut dosyasını çalıştırmak için sudo kullanın:

sudo ./myscript

4

Ne zaman böyle bir şey yapmak zorunda kalsam sadece kök haline gelirim:

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

Muhtemelen en iyi yol değil, ama işe yarıyor.


4

Bunu şu şekilde yaparım:

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

2
Kabuğu açıkça belirtmeniz gerekmediği için bu aslında biraz daha temiz görünüyor.
Steve Bennett

1
Küçük bir dezavantajı, ek bir işlem çalıştırmasıdır ( su): $ sudo su -c 'pstree -sp $$ >/dev/fd/1' init(1)───gnome-terminal(6880)───bash(6945)───sudo(401)───su(402)───bash(410)───pstree(411)
pabouk

3

Ölü atı vurmak istemem ama çok fazla cevaplar kullanımının burada vardır etmeyin teesize yönlendirmek zorunda araçları stdoutiçin/dev/null istemezsiniz ekranda bir kopya görmek istemediğiniz sürece .

Daha basit bir çözüm sadece şu şekilde kullanmaktır cat:

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

Yeniden yönlendirmenin tırnak içine nasıl konduğuna dikkat edin, böylece onu sudoçalıştıranın yerine başlayan bir kabuk tarafından değerlendirilir .


Bu gayet iyi çalışıyor. Neden tek olumsuz oy aldığını anlamıyorum. Upvoted.
Teemu Leisti

4
Bence çok fazla sevgi yok çünkü daha iyi değil sudo bash -c "ls -hal /root > /root/test.out". Tee kullanmak, bir mermiye ihtiyaç duymaz, ancak kedi buna ihtiyaç duymaz.
Nick Russo

2

Bu, ilgili cevaba dayanmaktadır tee. Ben küçük bir komut dosyası (ben diyoruz yazdım İşleri kolaylaştırmak için suwrite) ve koyun /usr/local/bin/ile +xizni:

#! /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

Kodda USAGE'de gösterildiği gibi , tek yapmanız gereken çıktıyı bu komut dosyasına ve ardından istenen süper kullanıcı tarafından erişilebilen dosya adına bağlamaktır ve gerekirse otomatik olarak şifrenizi girmenizi isteyecektir (içerdiği için sudo).

echo test | suwrite /root/test.txt

Bunun basit bir sarıcı olduğu için tee, tee'nin -aekleme seçeneğini de kabul edeceğini ve aynı anda birden fazla dosyaya yazmayı desteklediğini unutmayın.

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

Ayrıca /dev/, bu sayfadaki yorumlardan birinde belirtilen bir endişe olan cihazlara yazmaya karşı basit bir korumaya sahiptir .


1

Belki sadece bazı programlara / yollara sudo erişimi verilmiş olabilir? O zaman istediğini yapmanın bir yolu yok. (bir şekilde hacklemezseniz)

Durum böyle değilse, belki bash betiği yazabilirsiniz:

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

ctrl+ Tuşlarına basın d:

chmod a+x myscript.sh
sudo myscript.sh

Umarım yardımcı olur.


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

1
sudoZaten varsa , atyararlı ya da gerekli değil. sudo sh -c 'echo test >/tmp/test.out'aynı şeyi çok daha verimli ve zarif bir şekilde yapar (ancak yine de muhtemelen rootbu ayrıcalığa ihtiyaç duymayan şeyleri çalıştırdığınız kusurundan muzdariptir ; genellikle mümkün olduğunda ayrıcalıklı komutlardan kaçınmalısınız).
Üçlü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.