Comment utiliser sudo pour rediriger la sortie vers un emplacement où je ne suis pas autorisé à écrire?
-
09-06-2019 - |
Question
On m'a donné un accès sudo sur l'une de nos boîtes linux de développement RedHat et il me semble souvent que j'ai besoin de rediriger la sortie vers un emplacement auquel je n'ai pas normalement 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 le faire fonctionner?
La solution
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 existe plusieurs solutions:
-
Exécuter un shell avec sudo et lui donner 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
. Consultez la réponse de Steve Bennett si vous ne souhaitez 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 lorsque vous utilisez l'option-c
):sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
La redirection vers
/ dev / null
est nécessaire pour arrêter tee à partir de l'affichage à l'écran. Pour ajouter au lieu d'écraser le fichier de sortie (> >
), utiliseztee -a
outee --append
(le dernier est spécifique à GNU coreutils ).
Merci, rendez-vous sur Jd , Adam J. Forster et Johnathan pour les deuxième, troisième et quatrième solutions.
Autres conseils
Quelqu'un ici vient de suggérer un tee-shirt:
sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
Ceci peut é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 "écho à un fichier". programme, et la redirection vers / dev / null consiste à arrêter celui-ci d’afficher également à l’écran afin de le conserver identique à celui de l’exemple original ci-dessus.
Un truc que j'ai découvert moi-même était
sudo ls -hal /root/ | sudo dd of=/root/test.out
Le problème est que la commande est exécutée sous sudo
, mais que la redirection est exécutée sous votre utilisateur. Ceci est fait par le shell et vous ne pouvez rien y faire.
sudo command > /some/file.log
`-----v-----'`-------v-------'
command redirection
Les méthodes habituelles pour contourner ce problème sont les suivantes:
-
Emballez les commandes dans un script que vous appelez sous sudo.
Si les commandes et / ou le fichier journal changent, vous pouvez effectuer la script prend ces comme arguments. Par exemple:
sudo log_script command /log/file.txt
-
Appelez un shell et transmettez 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"
Encore une autre variation sur le thème:
sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF
Ou bien sûr:
echo 'ls -hal /root/ > /root/test.out' | sudo bash
Ils ont l’avantage (minuscule) de ne pas avoir à retenir les arguments de sudo
ou de sh
/ bash
Clarifier un peu pourquoi l’option de départ est préférable
En supposant que vous ayez la permission appropriée pour exécuter la commande qui crée la sortie, si vous dirigez la sortie de votre commande vers tee, il vous suffit d'élever les privilèges de tee avec sudo et de diriger directement tee pour écrire (ou ajouter) dans le fichier 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 généralement uniquement accessible en écriture pour root, qui est à l'origine de votre question.
C'est une bonne idée de le faire de cette manière 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 entièrement confiance, c’est crucial.
Notez que vous pouvez utiliser l'option -a pour créer un ajout (par exemple, > >
) au fichier cible au lieu de l'écraser (par exemple, >
). .
Faire en sorte que sudo exécute un shell, comme ceci:
sudo sh -c "echo foo > ~root/out"
Pour résoudre ce problème, voici comment:
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
Pourquoi ne pas é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
Je le ferais de cette façon:
sudo su -c 'ls -hal /root/ > /root/test.out'
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 solution, mais cela fonctionne.
Ne voulez pas vaincre un cheval mort, mais trop de réponses utilisent tee
, ce qui signifie que vous devez rediriger stdout
vers / dev / null
sauf si vous souhaitez voir une copie à l'écran. Une solution plus simple consiste à utiliser cat
comme ceci:
sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"
Notez 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.
Ceci est basé sur la réponse impliquant tee
. Pour simplifier les choses, j’écris un petit script (je l’appelle suwrite
) et le mets dans / usr / local / bin /
avec + x
. permission:
#! /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é dans USAGE dans le code, il vous suffit de diriger la sortie vers ce script suivi du nom de fichier souhaité, accessible au superutilisateur, qui vous demandera automatiquement votre mot de passe si nécessaire (car il 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 simultanée dans plusieurs fichiers. .
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 était une préoccupation mentionnée dans l'un des commentaires de cette page.
Peut-être n’avez-vous eu accès au sudo 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
Appuyez sur ctrl + d :
chmod a+x myscript.sh
sudo myscript.sh
J'espère que ça vous aidera.
sudo at now
at> echo test > /tmp/test.out
at> <EOT>
job 1 at Thu Sep 21 10:49:00 2017