How to write to a root-owned file using sudo

Writing to a file that requires root access in a non-root shell requires elevating privileges for the write operation. However, doing something like sudo echo "some text" > /path/to/root-owned-file will fail with a “Permission denied” error. This is because the shell sets up redirections before it executes the command. That means your non-root shell tries to open/truncate /path/to/root-owned-file for writing, but it lacks permission so the redirection fails and the command is never run. The sudo command would only elevate the program (echo), not the redirection done by the shell.

The usual solution is to use tee with sudo. The tee command reads from stdin and writes to both stdout and one or more files, and running it with sudo gives it root privileges to perform the write operation.

So, to overwrite a file:

echo "some text" | sudo tee /path/to/root-owned-file >/dev/null

The redirection to /dev/null is optional and just suppresses the tee’s output (otherwise it echoes the input). To append to a file use the tee’s -a option.

We can also write multiple lines to a root-owned file using a here-document:

sudo tee /path/to/root-owned-file >/dev/null <<'EOF'
This is the first line.
This is the second line.
$HOME will NOT expand here.
EOF

If you want shell variables (like $HOME) or command substitutions to expand, simply drop the quotes on the EOF delimiter of the herdoc.

While tee is generally preferred, there are other ways to achieve this. You can spawn a new shell with sudo and execute the command and its redirection within that new shell.

sudo bash -c 'echo "some text" > /path/to/root-owned-file'

To append, simply use the >> operator instead of >. For multi-line content, you can use a here-document within the new shell:

sudo bash -c 'cat > /path/to/root-owned-file << "EOF"
line 1
line 2
EOF'

This method works because the redirection happens in the root shell. The main drawback is the quoting complexity that arises from having to escape characters for both your current shell and the new root shell. As the content or command string grows, this can quickly become tedious and prone to errors. The sudo tee avoids this problem entirely by piping a data stream directly to the elevated command, making it a cleaner and more robust solution for writing to root-owned files.