How do I use sudo to redirect output to a location I don't have permission to write to?

293,739

Solution 1

Your command does not work because the redirection is performed by your shell which does not have the permission to write to /root/test.out. The redirection of the output is not performed by sudo.

There are multiple solutions:

  • Run a shell with sudo and give the command to it by using the -c option:

    sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • Create a script with your commands and run that script with sudo:

    #!/bin/sh
    ls -hal /root/ > /root/test.out
    

    Run sudo ls.sh. See Steve Bennett's answer if you don't want to create a temporary file.

  • Launch a shell with sudo -s then run your commands:

    [nobody@so]$ sudo -s
    [root@so]# ls -hal /root/ > /root/test.out
    [root@so]# ^D
    [nobody@so]$
    
  • Use sudo tee (if you have to escape a lot when using the -c option):

    sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
    

    The redirect to /dev/null is needed to stop tee from outputting to the screen. To append instead of overwriting the output file (>>), use tee -a or tee --append (the last one is specific to GNU coreutils).

Thanks go to Jd, Adam J. Forster and Johnathan for the second, third and fourth solutions.

Solution 2

Someone here has just suggested sudoing tee:

sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null

This could also be used to redirect any command, to a directory that you do not have access to. It works because the tee program is effectively an "echo to a file" program, and the redirect to /dev/null is to stop it also outputting to the screen to keep it the same as the original contrived example above.

Solution 3

A trick I figured out myself was

sudo ls -hal /root/ | sudo dd of=/root/test.out

Solution 4

The problem is that the command gets run under sudo, but the redirection gets run under your user. This is done by the shell and there is very little you can do about it.

sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection

The usual ways of bypassing this are:

  • Wrap the commands in a script which you call under sudo.

    If the commands and/or log file changes, you can make the script take these as arguments. For example:

    sudo log_script command /log/file.txt
    
  • Call a shell and pass the command line as a parameter with -c

    This is especially useful for one off compound commands. For example:

    sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
    
  • Arrange a pipe/subshell with required rights (i.e. sudo)

    # Read and append to a file
    cat ./'file1.txt' | sudo tee -a '/log/file.txt' > '/dev/null';
    
    # Store both stdout and stderr streams in a file
    { command1 arg; command2 arg; } |& sudo tee -a '/log/file.txt' > '/dev/null';
    

Solution 5

Yet another variation on the theme:

sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF

Or of course:

echo 'ls -hal /root/ > /root/test.out' | sudo bash

They have the (tiny) advantage that you don't need to remember any arguments to sudo or sh/bash

Share:
293,739
Jonathan
Author by

Jonathan

Started programming with Visual Basic 3.0, through 4-6 for the past fifteen years. Started using C# in a professional capacity in 2008. Started VB.NET 3.5 mid-2011 MSSQL 6.5 through all versions to SQL 2008, and a bit of Oracle, MySql, PostgreSQL Dabbled with web design on and off. Have played with Linux boxes for the last five years. Wrote a game in Objective-C to see if I could (yes) Started programming for iOS in 2011

Updated on July 19, 2022

Comments

  • Jonathan
    Jonathan almost 2 years

    I've been given sudo access on one of our development RedHat linux boxes, and I seem to find myself quite often needing to redirect output to a location I don't normally have write access to.

    The trouble is, this contrived example doesn't work:

    sudo ls -hal /root/ > /root/test.out
    

    I just receive the response:

    -bash: /root/test.out: Permission denied
    

    How can I get this to work?

    • Szabolcs Dombi
      Szabolcs Dombi almost 8 years
      use chmod u+w filename
    • Jonathan
      Jonathan almost 8 years
      @DombiSzabolcs You are suggesting that I create the file as sudo first, then give myself permission? Good idea.
    • tripleee
      tripleee about 5 years
      In many situations you end up here because you asked "why do I get Permission denied?" Sometimes the answer is that you do need to create a file as root (in which case proceed to read the answers) but very often, you simply need to create the file somewhere else, as yourself.
    • TingQian LI
      TingQian LI almost 5 years
      After struggling with these answers I finally choose to redirect to a temp file and sudo move it to destination.
    • Nate Eldredge
      Nate Eldredge about 4 years
    • Noel Yap
      Noel Yap almost 3 years
      NO! It is NOT generally a good idea to open up permissions to a file needing sudo permissions for security reasons. If you have sudo permissions, sudo bash (or your preferred shell) then perform the operations in that shell.
    • Shawn
      Shawn almost 3 years
      Given the large number of upvotes and answers, I feel like this post should be grandfathered in and reopened even though it isn't strictly on topic by the modern definition. It's still a very useful reference q&a to have.
  • kristianlm
    kristianlm about 11 years
    sudo dd is better than the sudo tee /root/file > /dev/null examples above!
  • Steve Bennett
    Steve Bennett almost 11 years
    That actually seems a bit cleaner, as you don't need to explicitly specify the shell.
  • Steve Bennett
    Steve Bennett almost 11 years
    nah, having to learn another weird, obscure command with weird, obscure syntax (of=..., really!) is not 'better'.
  • errant.info
    errant.info almost 11 years
    There's a great answer that tells you how to redirect STDERR and STDOUT separately here: stackoverflow.com/questions/692000/… ... basically perl -e 'print "STDIN\n"; print STDERR "STDERR\n"; ' > >( tee stdout.log ) 2> >( tee stderr.log >&2 )
  • rhlee
    rhlee almost 11 years
    dd is not a weird obscure command. It is used whenever you need to copy large amounts of data with buffering between two block devices. The syntax is actually pretty simple, dd is the command name, of=/root/test.out is the argument which tells dd what the Output Files is.
  • pabouk - Ukraine stay strong
    pabouk - Ukraine stay strong almost 11 years
    One small drawback is that it runs one additional process (su): $ sudo su -c 'pstree -sp $$ >/dev/fd/1' init(1)───gnome-terminal(6880)───bash(6945)───sudo(401)───su‌​(402)───bash(410)───‌​pstree(411)
  • Jonathan
    Jonathan over 10 years
    Sorry js3, but this has already been suggested (back in 2008) and is sitting at the second highest answer: stackoverflow.com/a/82553/6910
  • jg3
    jg3 over 10 years
    You're right, Jonathan, I'll update my answer to expand on the reasons why this is a preferable option. Thanks for the helpful feedback.
  • Urhixidur
    Urhixidur about 10 years
    You'll want to do 'sudo -E ...' in order to use variables in the shelled out command (when using this in a script, for instance).
  • blockloop
    blockloop about 10 years
    @steve Everything is 'obscure' until you learn what it is. of means output file and dd is a very popular tool used in both Linux and OSX (mostly for writing images to disks). This is a neat trick for sure.
  • thomasrutter
    thomasrutter almost 9 years
    Redirecting tee output to /dev/null is probably not necessary in a lot of cases where echoing the output to screen is harmless. For example, when dealing just with output of regular commands or contents of small text files.
  • thomasrutter
    thomasrutter almost 9 years
    dd is probably equally useful as tee here. In both cases you're using a common, well-known command for a purpose that, while slightly different to its original intended purpose, is still well-known and well-documented. While dd is good at copying huge amounts of data, it doesn't suck with small amounts. It has the benefit here of not echoing the output to standard output as well.
  • ali_m
    ali_m over 8 years
    Whenever you type words sudo dd next to one another, you want to make very, very sure that the arguments that follow are correct (especially considering its non-standard syntax). They don't call it "disk destroyer" for nothing...
  • Jonathan
    Jonathan almost 8 years
    How is this substantially different to answers above?
  • Hagen von Eitzen
    Hagen von Eitzen over 7 years
    In many cases, namely if the normal user has prmissions to perform the command and "only" cannot write to the desired output file, the first sudo (i.e., for the command itself) might be omitted
  • Teemu Leisti
    Teemu Leisti over 7 years
    This works just fine. I don't understand why it had one negative vote. Upvoted.
  • Nick Russo
    Nick Russo over 7 years
    I think it doesn't get much love because it's not much better than sudo bash -c "ls -hal /root > /root/test.out". Using tee avoids needing a shell, while cat does not.
  • Xen2050
    Xen2050 about 7 years
    @ali_m sudo dd is dangerous (I like the "data destroyer" name) but sudo tee and sudo cat are equally capable of overwriting drives. It should really be sudo that's the red flag, but it's used so often... I really watch out for /dev/sd... or anything in /dev/ that's not null or zero
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com almost 7 years
    And dd had more features than tee, e.g. status=progress is awesome for flashing images.
  • Francesc Rosas
    Francesc Rosas over 6 years
    Neat! Unfortunately, the append version is a bit too much verbose: ... | sudo dd of=out oflag=append conv=notrunc
  • Display Name
    Display Name almost 6 years
    Well actually this is not the same at all. dd by default works with blocks of 512 bytes and it can be dreaded slow. But tee tried to send data as fast as possible.
  • tripleee
    tripleee almost 6 years
    If you have sudo anyway, at isn't useful or necessary. sudo sh -c 'echo test >/tmp/test.out' does the same much more efficiently and elegantly (but still suffers from the flaw that you are probably running things as root which don't need that privilege; you should generally avoid privileged commands when you can).
  • jamadagni
    jamadagni over 5 years
    It's not "substantially different" but it clarifies the distinctive usage between replacing and appending to the file.
  • jamadagni
    jamadagni over 5 years
    A(nother) difference (apart from the /dev/null thing) between using tee and dd is that tee can be used to output to multiple files.
  • MortimerCat
    MortimerCat about 4 years
    This is the answer I copied to my cheat sheet.
  • dinesh saini
    dinesh saini about 2 years
    for reference: apart from tee other soultion i found good is sudo bash <<EOF echo -e "$(whoami)\n$(ls -l)\n$(pstree -sp $$)" > a whoami pstree -sp $$ EOF in heredoc statement shell expansion works so allowing command to be executed in not root environment and finally allowing all result redirected as sudo to priviledged file, here owener of file a is root.