95

I tried the following on the command prompt in bash:

sudo cat << EOF > /etc/yum.repos.d/some-name.repo
#Content
#....
#...
EOF

It complained :

-bash: /etc/yum.repos.d/some-name.repo: Permission denied

Then I did sudo su and tried the exact same thing except the sudo before cat, and it worked without any problem. What am I missing in the above ?

0

5 Answers 5

132

Output redirection (e.g., >) is performed by bash, not by cat, while running with your UID. To run with root's UID use sudo:

sudo bash -c 'cat << EOF > /etc/yum.repos.d/some-name.repo
line1
line2
line3
EOF'
3
  • The part I don't understand is that I am already using a bash prompt, then why I need abash -c.
    – iamauser
    Commented Sep 16, 2013 at 20:48
  • 1
    Because in this case redirection will be performed by bash started with "root" uid that have enough rights to write to /etc/yum.repos.d/. Commented Sep 16, 2013 at 20:51
  • 2
    You can use any other utility that redirect output. For example "cat << EOF | sudo tee /etc/yum.repos.d/some-name.repo" Commented Sep 16, 2013 at 20:53
79

Another option is tee.

cat << EOF | sudo tee -a /etc/yum.repos.d/some-name.repo
...
EOF
0
43

As a variation to @Yuriy Nazarov's answer, only the piped output needs to be elevated thru sudo. The piped input can stay un-elevated:

sudo bash -c 'cat > /etc/yum.repos.d/some-name.repo' << EOF
line1
line2
line3
EOF

This means a much smaller portion of the command needs to be quoted and sent thru to sudo.

2
  • 3
    This was a huge improvement over the accepted answer in my case, since my piped output was full of variables and shebangs and stuff. Commented Apr 1, 2020 at 18:17
  • I like how clean it is compared to the official answer. Commented Mar 26 at 19:38
12

As others have pointed out the shell redirection is done by the current shell not by cat. sudo only changes the permission of the program that is executed not of the shell doing the redirect. My solution to this is to avoid the redirect:

sudo dd of=/etc/yum.repos.d/some-name.repo << EOF
0
5

if you are using ' inside the text then you may use:

$ sudo bash -c "cat > /etc/postfix/mysql-virtual_forwardings.cf << EOF
user = mail_admin
password = password
dbname = mail
query = SELECT destination FROM forwardings WHERE source='%s'
hosts = 127.0.0.1
EOF
"

this is tested on google cloud's virtual server centos 7.0

Not the answer you're looking for? Browse other questions tagged or ask your own question.