Redirect Output to location with Permission denied Error?


Overview

We know that we can direct the standard output (std out) of a Linux shell script to a file by using the ">" operator at the end of the Linux shell script.

Sometimes, we need to redirect to a file which requires root permissions − for example, ‘sudo command > file_requires_root_.

If we use the ‘su’ command, we might get an “Access Denied” message even though we’ve used ‘su’.

We’ll look at the causes of this problem and see if there are any solutions.

Introduction to the Problem

A good example would be an explanation of the problem.

Let's say we have an empty plain text document called "output.txt".

kent$ ls -l /opt/output.txt
-rw-r--r-- 1 root root 0 May 8 10:43 /opt/output.txt

The ls command above shows that only user "root" can access the "/opt/output.txt" directory.

We now attempt to redirect the output from the echo statement to the specified text document as the regular user ken −

kent$ echo "Linux is awesome!" > /opt/output.txt
bash: /opt/output.txt: Permission denied

We've received an "Access Denied" error. It’s not difficult to understand. Because we execute the "echotest" script and redirect its output as the kent account, but the account kent doesn't have any permissions on the file /opt/.output.txt.

If we run a command using the "su" command, the command will be run as the superuser (root). Let's assume that the user kent has received the sudo privilege.

Let’s now see if we can redirect stdout (the default output) to our new text document using sudo −

kent$ sudo echo "Linux is awesome!" > /opt/output.txt
[sudo] password for kent:
bash: /opt/output.txt: Permission denied

After giving the password, we keep receiving the same error messages.

We may be asking why we're not allowed to write to the file even though we've used the sudo (super user) commands?

Now we need to find an answer to the question.

Why Do We Have the “Permission Denied” Error?

To understand the echo command, we need to first examine its full syntax. The command consists of two parts −

  • The command part: sudo echo “Linux is awesome!

  • The redirection part: > /opt/output.txt

When we use the sudo (super) privilege to run commands as the root account, the sudo doesn't change the redirection behavior.

Redirecting is still performed by the normal account ken. Therefore, we encounter an "Access Denied" error.

After understanding the cause of the problem (the lack of sleep), now we need to talk about the solution.

There are several different ways to approach solving this problem. Let’s look at them one by one.

  • Launching a “root” shell to execute the command

  • Wrapping the command in a shell script

  • Changing the redirection part into a command

  • Next, let’s look at these three approaches one by one.

Launching a “root” Shell to Execute the Command

If we can start an interactive bash session as the root user and run our commands there, then the redirection will also happen for root.

You can use the −s option when running the sudo su −c "echo 'Hello World' > /tmp/file" to create a root shell.

kent$ sudo -s
[sudo] password for kent:
[root]# echo "Linux is awesome!" > /opt/output.txt
[root]# exit
kent$ cat /opt/output.txt
Linux is awesome!

After running sudo −i, we're now in an interactive bash session with the superuser (or "superuser"). We can then run the whole command and redirecting as root.

The output was successfully saved to the target folder.

Wrapping the Command in a Shell Script

We can combine the two commands into one using sudo, which means that the redirection will be executed by the superuser (the user who has administrative privileges).

We can use a simple shell scripting technique to write an "echo" command into a text file.

kent$ cat myScript.sh
#!/bin/bash
echo "Linux is awesome! - (shell script)" > /opt/output.txt

Let’s first empty the output.txt file and then run our script.

kent$ sudo ./myScript.sh
[sudo] password for kent:
kent$ cat /opt/output.txt
Linux is awesome! - (shell script)

We expect our shell script to work as we expect.

It can be inconvenient if we're always creating shell scripts for command line programs with redirects.

To run a single shell script from within another shell script, we can use sudo sh −c "Script > File" to run the first shell script and redirect its output into the second shell script.

kent$ sudo bash -c 'echo "Linux is awesome! - (sub-shell)" > /opt/output.txt'
[sudo] password for kent:
kent$ cat /opt/output.txt
Linux is awesome! - (sub-shell)

Changing the Redirection Into a Command

From a previous section we know that the “su” command doesn’t affect the redirections. If we can change the redirections back into commands, we can run them with `su` once again.

The tilde (~) character is used to indicate an alternate location. We use it here to tell the shell where to look for our output. Then, we run sudo so that the shell executes the command as the root account. Finally, we use the tilde (~) character again to tell the shell where the output should go.

Now we're going to test this approach using an example.

kent$ sudo echo "Linux is awesome! - (using tee)" | sudo tee /opt/output.txt >/dev/null
[sudo] password for kent:
kent$ cat /opt/output.txt
Linux is awesome! - (using tee)

As the example above demonstrates, we've already calculated the expected value in the output.txt document.

We don't need to display the output from the tee because we're going to redirect its output to /dev/null instead.

Conclusion

If we run commands like sudo command > file_requires_root, we might encounter an error saying Permission Denial.

We've covered this issue in detail here, including its causes, solutions, and some best practices for avoiding it.

Updated on: 26-Dec-2022

507 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements