web-dev-qa-db-fra.com

Pourquoi Sudo cat donne-t-il une permission refusée mais Sudo vim fonctionne bien?

J'essaie d'automatiser l'ajout d'une source de référentiel dans le fichier pacman.conf de mon Arch, mais en utilisant la commande echo dans mon script Shell. Cependant, cela échoue comme ceci: -

Sudo echo "[archlinuxfr]" >> /etc/pacman.conf
Sudo echo "Server = http://repo.archlinux.fr/\$Arch" >> /etc/pacman.conf
Sudo echo " " >> /etc/pacman.conf

-bash: /etc/pacman.conf: Permission denied

Si j'apporte des modifications à /etc/pacman.conf manuellement à l'aide de vim, en effectuant

Sudo vim /etc/pacman.conf

et quitter vim avec :wq, tout fonctionne bien et mon fichier pacman.conf a été mis à jour manuellement sans réclamation "autorisation refusée".

Pourquoi cela est-il ainsi? Et comment puis-je obtenir Sudo echo travailler? (d'ailleurs, j'ai essayé d'utiliser Sudo cat aussi mais cela a échoué avec l'autorisation refusée aussi)

75
Calvin Cheng

Le problème est que la redirection est en cours de traitement par votre shell d'origine, et non par Sudo. Les coquilles ne sont pas capables de lire dans les pensées et ne savent pas que ce >> est destiné au Sudo et non à celui-ci.

Tu dois:

  1. cite la redirection (elle est donc transmise à Sudo)
  2. et utilise Sudo -s (de sorte que Sudo utilise un shell pour traiter la redirection indiquée.)
42
geekosaur

Comme @geekosaur l'a expliqué, le shell effectue la redirection avant d'exécuter la commande. Quand vous tapez ceci:

Sudo foo >/some/file

Votre processus Shell actuel crée une copie de lui-même qui tente d’abord d’ouvrir /some/file pour l'écriture, fait alors de ce descripteur de fichier sa sortie standard et n'exécute alors que Sudo.

Si vous y êtes autorisé (les configurations sudoer empêchent souvent de lancer des shells), vous pouvez faire quelque chose comme ceci:

Sudo bash -c 'foo >/some/file'

Mais je trouve une bonne solution en général est d'utiliser | Sudo tee au lieu de > et | 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, exécuter inutilement des processus en tant que root est précisément ce que Sudo a été créé pour éviter. Et utiliser echo en tant que root n’est que 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é et à sa propre sortie standard, et je n'ai pas besoin de le voir sur mon terminal. (La commande tee agit comme un connecteur "T" dans un pipeline physique, d'où son nom.) Et je suis passé aux guillemets simples ('...') au lieu de doubles ("...") pour que tout soit littéral et que je n’aie pas besoin de mettre une barre oblique inverse devant le $ dans $Arch.

Donc, cela prend soin d'écrire dans les fichiers en tant que root en utilisant Sudo. Maintenant, passons à une longue digression sur les manières de produire du texte contenant une nouvelle ligne dans un script Shell. :)

Tout d'abord, vous pouvez simplement regrouper tous les echo dans un sous-shell, de sorte que vous ne devez effectuer la redirection qu'une seule fois:

(echo '[archlinuxfr]
 echo 'Server = http://repo.archlinux.fr/$Arch'
 echo ' ') | Sudo tee -a /etc/pacman.conf >/dev/null

Ou utilisez printf au lieu de echo, de sorte que vous puissiez incorporer des nouvelles lignes directement dans la chaîne à l'aide de \n:

printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$Arch\n ' | 
  Sudo tee -a /etc/pacman.conf >/dev/null

Dans bash, vous pouvez obtenir le même résultat avec echo -e:

# BASH ONLY - NOT RECOMMENDED
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$Arch\n ' | 
  Sudo tee -a /etc/pacman.conf >/dev/null

Mais la plupart des obus ne feront que sortir le -e lorsque vous essayez cela, ce n’est donc pas recommandé.

Avec printf et echo -e, ce que la commande obtient sous la forme d’une chaîne d’argument contient une barre oblique inverse littérale suivie d’un N littéral partout où vous tapez \n, et le programme de commande lui-même (le code à l'intérieur de printf ou echo) le traduit en une nouvelle ligne. Dans de nombreux environnements modernes, vous avez la possibilité d’utiliser des guillemets ANSI $'...', qui traduira des séquences comme \n into littéral newlines avant que le programme de commande ne voie la chaîne, ce qui signifie que de telles chaînes fonctionnent avec n'importe quelle commande:

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.

Ce que je préférerais faire, ce serait d'utiliser un document ici et d'éviter le recours à echo ou printf entièrement:

Sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$Arch

EOF
113
Mark Reed

http://www.innovationsts.com/blog/?p=2758

Comme les instructions ne sont pas aussi claires que ci-dessus, j'utilise les instructions de cet article de blog. Avec des exemples, il est donc plus facile de voir ce que vous devez faire.

$ Sudo cat /root/example.txt | gzip> /root/example.gz
- bash: /root/example.gz: autorisation refusée

Notez que c’est la deuxième commande (la commande gzip) du pipeline qui provoque l’erreur. C’est là que notre technique consistant à utiliser bash avec l’option -c entre en jeu.

$ Sudo bash -c 'cat /root/example.txt | gzip> /root/example.gz '
$ Sudo ls /root/example.gz
/root/example.gz

La sortie de la commande ls indique que la création du fichier compressé a réussi.

La deuxième méthode est similaire à la première en ce sens que nous passons une chaîne de commande à bash, mais que nous le faisons dans un pipeline via Sudo.

$ Sudo rm /root/example.gz
$ echo "cat /root/example.txt | gzip> /root/example.gz" | Sudo bash
$ Sudo ls /root/example.gz
/root/example.gz

17
nelaaro
Sudo bash -c 'echo "[archlinuxfr]" >> /etc/pacman.conf'
6
Peyman Mahdian

STEP 1 créer une fonction dans un fichier bash (write_pacman.sh)

#!/bin/bash

function write_pacman {
 tee -a /etc/pacman.conf > /dev/null << 'EOF'
  [archlinuxfr]
  Server = http://repo.archlinux.fr/\$Arch
EOF
}

'EOF' ne interprétera pas $Arch variable.

STE2 fichier source bash

$ source write_pacman.sh

STEP exécuter la fonction

$ write_pacman
1
prayagupd