59

I am trying to follow what I assume is best practices of using sudo instead of root account.

I am running a simple concat file operation such as:

sudo echo 'clock_hctosys="YES"' >> /etc/conf.d/hwclock

This fails as to the right of the ">>" it is running as the normal user. Adding extra sudos also fails (expected behaviour since piping to the sudo command and not to the file).

Example is just that but it has been verified and tested under the root account.

74

You can invoke a new shell as root:

sudo sh -c 'echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock'

You could also just elevate a process to write to the file:

sudo tee -a /etc/conf.d/hwclock > /dev/null << EOF
clock_hctosys="YES"
EOF
  • 8
    In general the second option is more safe because only the tee commands runs as root, not the main command which could be complex and prone to misbehaviour. (not the case of echo) – pabouk Feb 14 '15 at 11:27
19

Another option, equally safe, is to use sudo's -i switch to log in as root:

$ sudo -i
# echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock'

This still follows best practice rules since the root account is not actually enabled as such but lets you do things as root safely. From man sudo:

The -i (simulate initial login) option runs the shell
    specified by the password database entry of the target user
    as a login shell.  This means that login-specific resource
    files such as .profile or .login will be read by the shell.
    If a command is specified, it is passed to the shell for
    execution via the shell's -c option.  If no command is
    specified, an interactive shell is executed. 
11

If you express your command without single quotes, you can put it inside single quotes and execute that via an intermediate shell.

To execute this as root:

echo 'clock_hctosys="YES"' >> /etc/conf.d/hwclock

Write the command a different way that doesn't use ':

echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock

Then invoke sudo sh -c …:

sudo sh -c 'echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock'

Alternatively, to write output to a file that only root can write to, call sudo tee. Pass the -a option to tee to append to the destination file, otherwise the file is truncated.

echo 'clock_hctosys="YES"' | sudo tee -a /etc/conf.d/hwclock >/dev/null

For more complex file modifications, you can call sudo sed, sudo ed, sudo perl, …

Alternatively, use a decent editor and make it call sudo. In Emacs, open /sudo:/etc/conf.d/hwclock. In Vim, call :w !sudo tee % to write to the opened file as root, or use the sudo.vim plugin. Or go from the sudo end and call sudoedit /etc/conf.d/hwclock.

Or you can give in to the dark side and run a shell as root.

$ sudo -i
# echo 'clock_hctosys="YES"' >> /etc/conf.d/hwclock
5

The command fails due to the permissions on the file redirected to. The redirection happens even before the sudo command is invoked.

You will have to make sure that it's root that actually openes the file for writing.

The simplest way of doing that:

echo 'clock_hctosys="YES"' | sudo tee -a /etc/conf.d/hwclock >/dev/null

The echo may be run as you ordinary user as it just produces a text string. The tee utility will have to run as root though, and tee -a will append data. We redirect the output to /dev/null because tee, by default, will duplicate its input data to its standard output in addition to writing to the indicated files.

With bash or any shell that understands "here-strings":

sudo tee -a /etc/conf.d/hwclock >/dev/null <<<'clock_hctosys="YES"'

This is identical in effect to the above. Only the way we produce the string is changed.


Another, slightly roundabout way of doing it:

sudo sh -c 'echo clock_hctosys=\"YES\" >>/etc/conf.d/hwclock'

Here, the redirection happens within a sh -c child shell running as root.

4

sudo dd of=

To append as you want:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc

or to recreate the file from scratch:

echo inbytes | sudo dd of=outfile

Advantages:

  • nicer than tee since no /dev/null redirection
  • nicer than sh since no subshell
  • dd has many powerful options, e.g. status=progress to see transfer progress

Works because sudo forwards stdin to the command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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