We've all run into problems like this:
$ echo 12000 > /proc/sys/vm/dirty_writeback_centisecs -bash: /proc/sys/vm/dirty_writeback_centisecs: Permission denied
The command fails because the target file is only writeable by root. The fix seems obvious and easy:
$ sudo echo 12000 > /proc/sys/vm/dirty_writeback_centisecs -bash: /proc/sys/vm/dirty_writeback_centisecs: Permission denied
Huh? It still fails. What gives? The reason it fails is that it is the shell that sets up the re-direction before running the command under sudo. The solution is to run the whole pipeline under sudo. There are several ways to do this:
echo 'echo 12000 > /proc/sys/vm/dirty_writeback_centisecs' | sudo sh sudo sh -c 'echo 12000 > /proc/sys/vm/dirty_writeback_centisecs' echo 12000 | sudo tee /proc/sys/vm/dirty_writeback_centisecs
This is fine for simple commands, but what if you have a complex command that already includes quotes and shell meta-characters?
Here's what I use for that:
sudo su <<\EOF echo 12000 > /proc/sys/vm/dirty_writeback_centisecs EOF
Note that the backslash before EOF is important to ensure meta-characters are not expanded.
Finally, here's an example of a command for which I needed to use this technique:
sudo sh << \EOF
perl -n -e '
use strict;
use warnings;
if (/^([^=]*=)([^\$]*)(.*)/) {
my $pre = $1;
my $path = $2;
my $post = $3;
(my $newpath = $path) =~ s/usr/usr\/local/;
$newpath =~ s/://g;
print "$pre$newpath:$path$post\n"
}
else {
print
}' < /opt/rh/ruby193/enable > /opt/rh/ruby193/enable.new
EOF
Comments