Syntax when using the 'exec' command

Hey gang,

I'm confused about the 'exec' command. I get the basics. I can redirect stdout and stderr to one log file with:

exec >> $logFile 2>&1

However, that code requires admin rights. In other scripts, when faced with this, I'll call 'sudo' and then pass a hashed password like this:

sudo -S touch $logFile <<< "${password}"

While the above code works great to run a command with admin rights, it doesn't work with the 'exec' command:

sudo -S exec >> $logFile 2>&1 <<< "${password}"

I'm guessing that either:

  1. my syntax is wrong or
  2. I can't use sudo in a redirect

With no assistance from the man page, I could use some help from the hive mind here. Thoughts?

Running the command:

sudo exec >> $logFile 2>&1

would setup a set-UID environment in which it will run the command:

exec >> $logFile 2>&1

and exit. Doing that seems pointless (the redirections will disappear when the command sudo ran completes and no redirections will have occurred in the current shell execution environment that your script will return to when the sudo is done).

If you want to run a script in a set-UID environment so it can open files to be used by that script, you need to use something more like:

sudo script_name
1 Like

I slightly disagree.

The command:

sudo exec >> $logFile 2>&1

will have the current, likely non privileged shell, redirect both stdout and stderr of the sudo command to the file named "$logfile", then sudo will (try to) run the regular exec command with no argument.

As it is very unlikely for a regular exec command to exist in the first place, being meaningless as an external command and only implemented as a builtin, this triggers an error message stating "sudo: exec: command not found" or similar written in "$logfile".

This log file will belong to the regular user running the command (at least if it wasn't already existing), not root.

1 Like

The debate over what my previous code may or may not do is worthwhile but not the point of my post. The point was to ask: how can i automate -- inside of the script -- for stdout and stderr to be re-directed to the same file, something that usually requires entering an admin password.

Thank you for helping to focus on that.

The simplest approach would be to use ACLs and grant the current user the right to write to the logfile. That would require using an OS and file system that support ACLs though and the syntax will vary depending on the OS and the kind of ACLs supported.

That is easy.

exec 1>filename
exec 2>&1

echo "from stderr" >&2
echo "from stdout"

None of the above requires root... I think you will discover that the problem is not exec -- the problem is the file itself. Perhaps the file is owned by root, preventing you from writing to it? Show ls -l filename please.

If your script runs with insufficient permissions, it cannot get more. Period. Full stop.

Either run it with sufficient permissions or fix the file so it doesn't need extra permissions.

Hi jlliagre,
Yes. You are correct. To get what I was describing in post #2, you would need to use:

sudo sh -c "exec >> $logFile 2>&1"

We are sorry that you are not interested in understanding why what you have asked cannot be done. That doesn't alter the fact that IT CANNOT BE DONE. Either you have permission to open the file to which you want to redirect output for writing without extended privileges, or you run the entire script with extended privileges. Redirecting output to a file in a sudo command will not grant other parts of that script that are not being run with extended privileges the ability to write to a file that it can't open for writing.

You could use sudo in your script to make the log file writeable by everyone using chmod . You could use sudo to run chown or chgrp to change the file's owner and/or group so you can write to it. You could use sudo to set an ACL allowing your user-ID or group-ID write access (if your system supports ACLs). Or, as I suggested in post #2, you could elevate the privileges of your entire script by running it with sudo . But, you cannot redirect output to a file that you don't have permission to write to in a sudo command to make that file writeable by the remainder of that script.

@Hungryd, should the ACL way doesn't suit your needs, here is an alternative:

mkfifo /tmp/fifo$$
sudo dd if=/tmp/fifo$$ of=$logFile &
pid=$!
exec >/tmp/fifo$$ 2>&1
...
run whatever commands you like as the regular user here 
...
rm /tmp/fifo$$
exec >/dev/tty 2>&1
sudo kill $pid

It is actually number 2.

I hopefully won't distract too much from the focus of the thread by providing a few words on how sudo works. Here it goes:

sudo works by providing rules to run processes under different user-privileges than the current one. Basically

sudo /some/command -opt arg1 arg2

is the same as su -ing to another user (usually root , but it could be any other either), then executing said command - that is: creating a process - and then switching back immediately.

su - otheruser
/some/command -opt arg1 arg2
exit

The keyword here is process. If you enter a command (via commandline or from a script, it doesn't matter) a process is created which does something for you.

exec creates no process, it is just a shell keyword. Therefore sudo cannot work with it, like it cannot work with if , while or any other keyword the shell uses.

The solution is to either not use sudo but other means (like ACLs, FIFOs, better suited filemodes for log files, group rights, ... like you have been told already) or create a process which sudo can work with. As perhaps you will want to not only redirect your own messages generated with print or similar shell commands but also the output from arbitrary executables this is not possible at all.

Personally i would suggest to make such logfiles writable for a certain group, do the same for the scripts in question and then either put everybody who should be able to execute these scripts into this group or use sudo -rules to let select groups (UNIX groups or select users) use these scripts. Instead of fiddling around with Rube-Goldberg-methods just use the classical UNIX toolbox like it is meant to be used: groups were actually invented for exactly that purpose of allowing a group of users and their processes to do what other users (and their processes) can't.

I hope this helps.

bakunin

1 Like