Come posso usare sudo per redirect l’output in una posizione a cui non ho il permesso di scrivere?

Mi è stato concesso l’accesso sudo su uno dei nostri box di sviluppo RedHat Linux, e mi sembra di trovarmi abbastanza spesso a dover redirect l’output in una posizione in cui normalmente non ho accesso in scrittura.

Il problema è che questo esempio forzato non funziona:

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

Ho appena ricevuto la risposta:

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

Come posso farlo funzionare?

Il tuo comando non funziona perché il reindirizzamento è eseguito dalla tua shell che non ha il permesso di scrivere su /root/test.out . Il reindirizzamento dell’output non viene eseguito da sudo.

Ci sono più soluzioni:

  • Esegui una shell con sudo e dagli il comando usando l’opzione -c :

     sudo sh -c 'ls -hal /root/ > /root/test.out' 
  • Crea uno script con i tuoi comandi ed esegui quello script con sudo:

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

    Esegui sudo ls.sh Vedi la risposta di Steve Bennett se non vuoi creare un file temporaneo.

  • Avvia una shell con sudo -s quindi esegui i tuoi comandi:

     [[email protected]]$ sudo -s [[email protected]]# ls -hal /root/ > /root/test.out [[email protected]]# ^D [[email protected]]$ 
  • Usa sudo tee (se devi scappare molto usando l’opzione -c ):

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

    Il reindirizzamento a /dev/null è necessario per impedire a T di uscire sullo schermo. Per aggiungere invece di sovrascrivere il file di output ( >> ), utilizzare tee -a o tee --append (l’ultimo è specifico per coreutils GNU ).

Grazie a Jd , Adam J. Forster e Johnathan per la seconda, terza e quarta soluzione.

Qualcuno qui ha appena suggerito sudoing tee:

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

Questo potrebbe anche essere usato per redirect qualsiasi comando, in una directory alla quale non si ha accesso. Funziona perché il programma tee è effettivamente un programma “echo to a file”, e il reindirizzamento a / dev / null è quello di interrompere anche l’output sullo schermo per mantenerlo uguale all’esempio originale originale sopra.

Era un trucco che ho scoperto

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

Il problema è che il comando viene eseguito su sudo , ma il reindirizzamento viene eseguito sotto il tuo utente. Questo è fatto dalla shell e c’è ben poco che puoi fare al riguardo.

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

I soliti modi per aggirare questo sono:

  • Avvolgi i comandi in uno script che chiami su sudo.

    Se i comandi e / o il file di registro cambiano, è ansible impostare lo script come argomenti. Per esempio:

     sudo log_script command /log/file.txt 
  • Chiama una shell e passa la riga di comando come parametro con -c

    Questo è particolarmente utile per i comandi composti da una sola uscita. Per esempio:

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

Ancora un’altra variazione sul tema:

 sudo bash < /root/test.out EOF 

O ovviamente:

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

Hanno il (piccolo) vantaggio che non è necessario ricordare alcun argomento su sudo o sh / bash

Chiarire un po ‘perché l’opzione tee è preferibile

Supponendo che tu abbia il permesso appropriato per eseguire il comando che crea l’output, se colleghi l’output del tuo comando a tee, devi solo elevare i privilegi di tee con sudo e tee diretto per scrivere (o accodare) al file in questione.

nell’esempio fornito nella domanda ciò significherebbe:

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

per un paio di altri esempi pratici:

 # 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 

In ognuno di questi esempi si sta eseguendo l’output di un comando non privilegiato e si scrive su un file che di solito è scrivibile solo da root, che è l’origine della domanda.

È una buona idea farlo in questo modo perché il comando che genera l’output non viene eseguito con privilegi elevati. Non sembra importare qui con echo ma quando il comando source è uno script di cui non ti fidi completamente, è fondamentale.

Nota puoi usare l’opzione -a per tee per aggiungere append (come >> ) al file di destinazione piuttosto che sovrascriverlo (come > ).

Fai sudo eseguire una shell, in questo modo:

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

Che ne dici di scrivere una sceneggiatura?

Nome file: myscript

 #!/bin/sh /bin/ls -lah /root > /root/test.out # end script 

Quindi usa sudo per eseguire lo script:

 sudo ./myscript 

Il modo in cui vorrei andare su questo problema è:

Se hai bisogno di scrivere / sostituire il file:

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

Se è necessario aggiungere al file:

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

Lo farei in questo modo:

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

Ogni volta che devo fare qualcosa del genere divento semplicemente root:

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

Probabilmente non è il modo migliore, ma funziona.

Ecco un’estensione della risposta che coinvolge il tee. Per semplificare le cose, ti piacerebbe creare un piccolo script (io lo chiamo suwrite o potresti chiamarlo sutee) e metterlo in / usr / local / bin / con l’authorization + x:

 #! /bin/sh sudo tee [email protected] > /dev/null 

Ora tutto ciò che dovete fare è canalizzare l’output in questo script seguito dal nome file desiderato accessibile dal superutente e, se necessario, vi chiederà automaticamente la password (dato che include sudo).

 echo test | suwrite /root/test.txt 

Nota che poiché questo è un semplice wrapper per tee, accetta anche l’opzione tee -a (o qualsiasi altra) in modo tale da aggiungere al file desiderato solo pass -a:

 echo test | suwrite -a /root/test.txt 

Non intendo battere un cavallo morto, ma qui ci sono troppe risposte che usano il tee , il che significa che devi redirect lo stdout su /dev/null meno che tu non voglia vedere una copia sullo schermo. Una soluzione più semplice è quella di usare solo cat questo modo:

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

Si noti come il reindirizzamento viene inserito tra virgolette in modo che venga valutato da una shell avviata da sudo anziché da quella in esecuzione.

Forse ti è stato concesso l’accesso sudo solo ad alcuni programmi / percorsi? Quindi non c’è modo di fare quello che vuoi. (a meno che non lo modifichiate in qualche modo)

Se non è il caso, allora forse puoi scrivere script bash:

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

Premi CTRL + D :

 chmod a+x myscript.sh sudo myscript.sh 

Spero che aiuti.

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