When using sudo to allow edits to files, I regularly get 'permission denied'.
For example, my mouse is jittery and sluggish, so I want to disable polling:
sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.confI'm prompted for a password, and then get:
bash: /etc/modprobe.d/local.conf: Permission deniedSo I tried to do a temporary change to disable polling by using:
sudo echo N> /sys/module/drm_kms_helper/parameters/pollYet again the system responded with:
bash: /sys/module/drm_kms_helper/parameters/poll: Permission deniedAny ideas?
17 Answers
Output redirection (via the > operator) is done by the shell, not by echo. You have to login as root
sudo -iThen you can use redirection
echo N> /sys/module/drm_kms_helper/parameters/pollOtherwise you can run bash string with sudo
sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll" 5 The output redirection is done by the shell from which the command has been invoked. So, breaking everything into bits, here what is happening*:
shell invokes
sudo echo "options drm_kms_helper poll=N", which executessudocommand withecho "options drm_kms_helper poll=N"command linesudo asks for a password, opens superuser shell and invokes
echo "options drm_kms_helper poll=N", which runsechocommand passing it"options drm_kms_helper poll=N"echo, running with
rootprivileges, prints the string to its standard output.echocommand terminates, superuser shell exits,sudoterminatesthe shell from which the command has been invoked collects the output and tries to redirect it to
/etc/modprobe.d/local.conf, which is writeable only by root. It gets "permission denied" error.
For the ways to fix this see @shantanu answer.
(*) - while the above sequence helps to understand why the command fails, in reality things happen somewhat out-of-order: the original shell notices the redirection and tries to open the file for writing before invoking the sudo ... command. When opening the file fails the shell doesn't even invoke the command which was supposed to write to the file (thanks to @PanosRontogiannis for pointing this out).
Here's a quick test:
$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission deniedIn the test above the whoami | tee who.txt was going to create a file named who.txt containing the word "root". However, when the output redirection fails in the calling shell, "who.txt" file is also missing because the command was not invoked.
You can use a tee command like this:
sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10Or if its a command's output:
echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/pollIf you had a situation where you wanted to append rather than overwrite the target file--that is, to make tee behave like >> rather than >--you would use tee -a.
An approach I haven't seen mentioned here is to simply execute the entire commandline in its own shell. The sudo manpage itself gives an example of this approach:
To make a usage listing of the directories in the /home partition. Note that this runs the commands in a sub-shell to make the cd and file redirection work.
$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" 0 Another option is to use a temporary file. This is useful in a bash script.
temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever sudo dd of=
To append as you want:
echo inbytes | sudo dd of=outfile oflag=append conv=notruncor to recreate the file from scratch:
echo inbytes | sudo dd of=outfileAdvantages:
- nicer than
teesince no/dev/nullredirection - nicer than
shsince no explicit subshell (but an implicit one for the redirection) ddhas many powerful options, e.g.status=progressto see transfer progress: How to show the transfer progress and speed when copying files with cp?
Works because sudo forwards stdin to the command.
1Create a one-line script from your command, then execute the script as sudo. For example:
Use an editor to create a file; for example:
nano my_script.shIn the editor, insert your shebang, and the command:
#!/bin/bash echo "options drm_kms_helper poll=N" > /etc/modprobe.d/local.confSave the file & exit the editor; e.g.
~/my_script.shMake the file executable:
chmod 755 ~/my_script.shRun the script under
sudo:sudo ./my_script.sh