web-dev-qa-db-fra.com

Comment utiliser Sudo pour rediriger la sortie vers un emplacement où je ne suis pas autorisé à écrire?

Sudo a été autorisé à accéder à l’une de nos boîtes linux de développement RedHat et j’ai souvent l'impression de devoir rediriger la sortie vers un emplacement auquel je n'ai normalement pas accès en écriture.

Le problème, c'est que cet exemple artificiel ne fonctionne pas:

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

Je viens de recevoir la réponse:

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

Comment puis-je obtenir que cela fonctionne?

760
Jonathan

Votre commande ne fonctionne pas car la redirection est effectuée par votre shell, qui n'a pas le droit d'écrire dans /root/test.out. La redirection de la sortie n'est pas effectuée par Sudo.

Il y a plusieurs solutions:

  • Exécutez un shell avec Sudo et donnez-lui la commande en utilisant l'option -c:

    Sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • Créez un script avec vos commandes et exécutez-le avec Sudo:

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

    Exécutez Sudo ls.sh. Voir answer de Steve Bennett si vous ne voulez pas créer de fichier temporaire.

  • Lancez un shell avec Sudo -s puis lancez vos commandes:

    [nobody@so]$ Sudo -s
    [root@so]# ls -hal /root/ > /root/test.out
    [root@so]# ^D
    [nobody@so]$
    
  • Utilisez Sudo tee (si vous devez échapper beaucoup en utilisant l'option -c):

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

    La redirection vers /dev/null est nécessaire pour empêcher tee de sortir à l'écran. Pour ajouter au lieu de remplacer le fichier de sortie .__ (>>), utilisez tee -a ou tee --append (le dernier est spécifique à GNU coreutils ).

Merci à Jd , Adam J. Forster et Johnathan pour les deuxième, troisième et quatrième solutions.

1068
Cristian Ciupitu

Quelqu'un ici vient de suggérer un tee-shirt:

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

Cela pourrait également être utilisé pour rediriger n'importe quelle commande vers un répertoire auquel vous n'avez pas accès. Cela fonctionne parce que le programme tee est en réalité un programme "echo to a file" et que la redirection vers/dev/null consiste à l'arrêter, ainsi qu'à l'affichage à l'écran, afin de le conserver identique à l'exemple original ci-dessus.

89
Jonathan

Un truc que j'ai imaginé moi-même était

Sudo ls -hal /root/ | Sudo dd of=/root/test.out
70
rhlee

Le problème est que command est exécuté sous Sudo, mais que redirection est exécuté sous votre utilisateur. Ceci est fait par Shell et vous ne pouvez rien y faire.

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

Les moyens habituels de contourner cela sont:

  • Enveloppez les commandes dans un script que vous appelez sous Sudo.

    Si les commandes et/ou le fichier journal changent, vous pouvez faire en sorte que le script Les utilise comme arguments. Par exemple:

    Sudo log_script command /log/file.txt
    
  • Appeler un shell et passer la ligne de commande en tant que paramètre avec -c

    Ceci est particulièrement utile pour certaines commandes composées . Par exemple:

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

Encore une autre variation sur le thème:

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

Ou bien sur:

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

Ils ont le (petit) avantage que vous n'avez pas besoin de vous souvenir des arguments pour Sudo ou sh/bash

19
Steve Bennett

Clarifier un peu pourquoi l'option du tee est préférable

En supposant que vous disposiez de l'autorisation appropriée pour exécuter la commande qui crée la sortie, si vous dirigez la sortie de votre commande vers tee, il vous suffira d'élever les privilèges de tee avec Sudo et de demander à tee d'écrire (ou d'ajouter) au fichier en question.

dans l'exemple donné dans la question, cela signifierait:

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

pour quelques exemples plus pratiques:

# 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

Dans chacun de ces exemples, vous prenez le résultat d'une commande non privilégiée et écrivez dans un fichier qui n'est généralement accessible en écriture que par root, qui est l'origine de votre question.

C'est une bonne idée de le faire de cette façon car la commande qui génère la sortie n'est pas exécutée avec des privilèges élevés. Cela ne semble pas avoir d’importance ici avec echo, mais lorsque la commande source est un script auquel vous ne faites pas complètement confiance, c’est crucial.

Notez que vous pouvez utiliser l'option -a pour créer un ajout (comme >>) au fichier cible plutôt que de l'écraser (comme >).

18
jg3

Faites que Sudo exécute un shell, comme ceci:

Sudo sh -c "echo foo > ~root/out"
15
Penfold

La façon dont je voudrais aborder ce problème est la suivante:

Si vous devez écrire/remplacer le fichier:

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

Si vous devez ajouter au fichier:

echo "some text" | Sudo tee -a /path/to/file
8
Nikola Petkanski

Que diriez-vous d'écrire un script?

Nom de fichier: myscript

#!/bin/sh

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

# end script

Ensuite, utilisez Sudo pour exécuter le script:

Sudo ./myscript
5
Jd

Je le ferais de cette façon:

Sudo su -c 'ls -hal /root/ > /root/test.out'
4
fardjad

Chaque fois que je dois faire quelque chose comme ça, je deviens simplement root:

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

Ce n'est probablement pas la meilleure façon, mais cela fonctionne.

3
Adam J. Forster

Ne voulez pas battre un cheval mort, mais il y a trop de réponses ici qui utilisent tee, ce qui signifie que vous devez rediriger stdout vers /dev/null à moins que vous ne vouliez voir une copie à l'écran. Une solution plus simple consiste simplement à utiliser cat comme ceci:

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

Remarquez comment la redirection est placée entre guillemets afin qu'elle soit évaluée par un Shell démarré par Sudo au lieu de celui qui l'exécute.

3
haridsv

Ceci est basé sur la réponse impliquant tee. Pour faciliter les choses, j’écris un petit script (je l’appelle suwrite) et le mets dans /usr/local/bin/ avec la permission +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

Comme indiqué dansUSAGEdans le code, il vous suffit de diriger la sortie vers ce script, suivi du nom de fichier souhaité accessible par superutilisateur, qui vous demandera automatiquement votre mot de passe si nécessaire (car comprend Sudo).

echo test | suwrite /root/test.txt

Notez que puisqu'il s'agit d'un simple wrapper pour tee, il acceptera également l'option -a de tee à ajouter, et prend également en charge l'écriture dans plusieurs fichiers en même temps.

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

Il dispose également d’une protection simpliste contre l’écriture sur les périphériques /dev/, ce qui est une préoccupation mentionnée dans l’un des commentaires de cette page.

2
jamadagni

Peut-être que Sudo n’a accès qu’à certains programmes/chemins? Ensuite, il n'y a aucun moyen de faire ce que vous voulez. (sauf si vous allez le pirater d'une manière ou d'une autre)

Si ce n'est pas le cas, vous pouvez peut-être écrire le script bash:

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

Presse ctrl + d :

chmod a+x myscript.sh
Sudo myscript.sh

J'espère que ça vous aidera.

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