Comment résoudre "permission denied" lors de l'utilisation de sudo avec redirection dans Bash?

115

Lorsque vous utilisez sudo pour autoriser les modifications de fichiers, je reçois régulièrement une autorisation refusée.

Par exemple, ma souris est nerveuse et lente, je veux donc désactiver l’interrogation:

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

Je suis invité à entrer un mot de passe, puis à obtenir:

bash: /etc/modprobe.d/local.conf: Permission denied

J'ai donc essayé de faire un changement temporaire pour désactiver l'interrogation en utilisant:

sudo echo N> /sys/module/drm_kms_helper/parameters/poll

Encore une fois, le système a répondu avec:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

Des idées?

    
posée Jack 19.12.2012 - 05:12
la source

6 réponses

123

La redirection de la sortie (via l’opérateur > ) est effectuée par le shell et non par echo . Vous devez vous connecter en tant que root

sudo -i

Ensuite, vous pouvez utiliser la redirection

echo N> /sys/module/drm_kms_helper/parameters/poll

Sinon, vous pouvez lancer la chaîne bash avec sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
    
réponse donnée shantanu 19.12.2012 - 05:22
la source
70

La redirection de sortie est effectuée par le shell à partir duquel la commande a été invoquée . Donc, tout casser en morceaux, voici ce qui se passe *:

    Le shell
  • appelle sudo echo "options drm_kms_helper poll=N" , qui exécute la commande sudo avec la ligne de commande echo "options drm_kms_helper poll=N"

  • sudo demande un mot de passe, ouvre le shell super-utilisateur et appelle echo "options drm_kms_helper poll=N" , qui exécute la commande echo en lui transmettant "options drm_kms_helper poll=N"

  • echo, exécuté avec les privilèges root , imprime la chaîne à sa sortie standard.

  • La commande echo se termine, le shell du superutilisateur se ferme, sudo se termine

  • le shell à partir duquel la commande a été appelée collecte la sortie et tente de la rediriger vers /etc/modprobe.d/local.conf , qui n'est accessible en écriture que par root. Il obtient une erreur "autorisation refusée".

Pour savoir comment résoudre ce problème, consultez la réponse à @shantanu.

(*) - alors que la séquence ci-dessus aide à comprendre pourquoi la commande échoue, en réalité, les choses se passent un peu dans le désordre: le shell d'origine remarque la redirection et tente d'ouvrir le fichier avant d'appeler le sudo ... commander. A l'ouverture du fichier, le shell n'invoque même pas la commande supposée écrire dans le fichier (merci à @PanosRontogiannis de le signaler).

Voici un test rapide:

$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

Dans le test ci-dessus, le whoami | tee who.txt allait créer un fichier nommé who.txt contenant le mot "root". Cependant, lorsque la redirection de sortie échoue dans le shell appelant, le fichier "who.txt" est également manquant car la commande n'a pas été appelée.

    
réponse donnée Sergey 19.12.2012 - 06:19
la source
55

Ajouter à la réponse de Shantanu:

... Ou vous pouvez utiliser une commande tee comme ceci:

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

ou si c'est la sortie d'une commande:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
    
réponse donnée Untitled 19.12.2012 - 07:50
la source
13

Une approche que je n'ai pas vue mentionnée ici consiste à exécuter simplement la ligne de commande entière dans son propre shell. La page de manuel sudo elle-même donne un exemple de cette approche:

  

Pour créer une liste d’utilisation des répertoires de la partition / home. Notez que cela exécute les commandes dans un sous-shell pour que la redirection de cd et de fichier fonctionne.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
    
réponse donnée kojiro 19.12.2012 - 14:53
la source
2

Une autre option consiste à utiliser un fichier temporaire. Ceci est utile dans un script bash.

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever
    
réponse donnée user545424 29.07.2014 - 17:51
la source
2

sudo dd of=

Pour ajouter comme vous voulez:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc

ou pour recréer le fichier à partir de zéro:

echo inbytes | sudo dd of=outfile

Avantages:

  • plus joli que tee depuis aucune redirection de /dev/null
  • plus joli que sh depuis aucun sous-shell explicite (mais implicite pour la redirection)
  • dd a de nombreuses options puissantes, par ex. status=progress pour voir la progression du transfert

Fonctionne car sudo transmet stdin à la commande.

    
la source

Lire d'autres questions sur les étiquettes