Comme l'explique @geekosaur, le shell effectue la redirection avant d'exécuter la commande. Quand vous tapez ceci :
sudo foo >/some/file
Votre processus shell actuel fait une copie de lui-même qui essaie d'abord d'ouvrir /some/file
pour l'écriture, puis si cela réussit, il fait de ce descripteur de fichier sa sortie standard, et seulement si cela réussit, il exécute sudo
. C'est un échec dès la première étape.
Si vous y êtes autorisé (les configurations sudoer empêchent souvent l'exécution de shells), vous pouvez faire quelque chose comme ceci :
sudo bash -c 'foo >/some/file'
Mais je trouve qu'une bonne solution en général est d'utiliser | sudo tee
au lieu de >
y | sudo tee -a
au lieu de >>
. C'est particulièrement utile si la redirection est la seule raison pour laquelle j'ai besoin de sudo
en premier lieu ; après tout, faire tourner inutilement des processus comme Root est précisément ce qui sudo
a été créé pour éviter. Et courir echo
comme Root est tout simplement stupide.
echo '[archlinuxfr]' | sudo tee -a /etc/pacman.conf >/dev/null
echo 'Server = http://repo.archlinux.fr/$arch' | sudo tee -a /etc/pacman.conf >/dev/null
echo ' ' | sudo tee -a /etc/pacman.conf >/dev/null
J'ai ajouté > /dev/null
à la fin parce que tee
envoie sa sortie à les deux le fichier nommé y sa propre sortie standard, et je n'ai pas besoin de la voir sur mon terminal. (Les tee
agit comme un connecteur en "T" dans un pipeline physique, d'où son nom). Et je suis passé aux guillemets simples ( '
... '
) au lieu de doubles ( "
... "
) afin que tout soit littéral et que je n'aie pas à mettre une barre oblique inversée devant le nom de l'utilisateur. $
en $arch
. (Sans les guillemets ni la barre oblique inversée, $arch
serait remplacé par la valeur du paramètre shell arch
qui n'existe probablement pas, auquel cas l'option $arch
est remplacé par rien et disparaît tout simplement).
Cela permet de s'occuper de l'écriture dans les fichiers en tant que Root en utilisant sudo
. Maintenant, une longue digression sur les moyens de produire du texte contenant des nouvelles lignes dans un shell script. :)
Afin de le mettre en valeur, comme on dit, ma solution préférée serait d'introduire un document ici dans la méthode ci-dessus. sudo tee
Il n'est donc pas nécessaire d'utiliser la commande cat
o echo
o printf
ou toute autre commande. Les guillemets simples se sont déplacés vers l'introduction de la sentinelle <<'EOF'
mais ils ont le même effet ici : le corps est traité comme du texte littéral, donc $arch
est laissé seul :
sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch
EOF
Mais si c'est ainsi que je procéderais, il existe des alternatives. En voici quelques-unes :
Vous pouvez vous en tenir à un seul echo
par ligne, mais regroupez-les toutes dans un sous-shell, de sorte que vous n'ayez à ajouter au fichier qu'une seule fois :
(echo '[archlinuxfr]'
echo 'Server = http://repo.archlinux.fr/$arch'
echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null
Si vous ajoutez -e
à la echo
(et que vous utilisez un interpréteur de commandes qui prend en charge cette extension non-POSIX), vous pouvez intégrer les nouvelles lignes directement dans la chaîne de caractères en utilisant la commande \n
:
# NON-POSIX - NOT RECOMMENDED
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Mais comme il est dit plus haut, ce n'est pas un comportement spécifié par POSIX ; votre shell pourrait simplement renvoyer un texte littéral -e
suivi d'une chaîne de caractères contenant un tas de caractères littéraux \n
à la place. La manière POSIX de faire cela est d'utiliser printf
au lieu de echo
; il traite automatiquement son argument comme echo -e
le fait, mais n'ajoute pas automatiquement une nouvelle ligne à la fin, vous devez donc ajouter une ligne supplémentaire à la fin de la ligne. \n
là aussi :
printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' |
sudo tee -a /etc/pacman.conf >/dev/null
Avec l'une ou l'autre de ces solutions, ce que la commande obtient comme chaîne d'arguments contient la séquence de deux caractères \n
et c'est au programme de commande lui-même (le code à l'intérieur de la commande) d'agir. printf
o echo
) pour le traduire en une nouvelle ligne. Dans de nombreux shells modernes, vous avez la possibilité d'utiliser les guillemets ANSI $'
... '
qui traduira des séquences comme \n
en littéral des retours à la ligne avant que le programme de commande ne voie la chaîne. Cela signifie que de telles chaînes de caractères fonctionnent avec n'importe quelle commande, y compris la bonne vieille -e
-moins echo
:
echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Mais, bien que plus portable que echo -e
les guillemets ANSI sont toujours une extension non-POSIX.
Et encore une fois, bien que ce soient toutes des options, je préfère la ligne droite. tee <<EOF
solution ci-dessus.
3 votes
Duplication possible de Comment utiliser sudo pour rediriger la sortie vers un emplacement où je n'ai pas la permission d'écrire ?