Execute a line of commands with one sudo
Solution 1
You can't just stick sudo
in front of a shell command, you have to invoke a shell to evaluate that command again (doing things like expanding variables, opening files for redirection operators, etc.). So that's
sudo bash -c !!
except that this doesn't quite work, because !!
interpolates the text of the previous command, special characters and all. You need to retrieve the text of the command as a string and pass that as an argument to sh
. Fortunately, bash's fc
builtin lets you do that¹.
sudo bash -c "$(fc -ln -1)"
Or even, to be sure to invoke the same version of bash that's currently running:
sudo "$BASH" -c "$(fc -ln -1)"
Note that since the command is executed in a separate shell process, it inherits environment variables (only the ones that sudo
preserves, mind), but not shell internal variables. Shell options (e.g. kshglob
) and other settings will start from the default either.
The same command² works in zsh and ksh, though ATT ksh93 requires both the first
and last
number to be passed to fc
³ (which also works in bash, zsh and pdksh/mksh):
sudo zsh -c "$(fc -ln -1)"
sudo ksh -c "$(fc -ln -1 -1)"
sudo "$0" -c "$(fc -ln -1 -1)"
Using $0
to designate the executable of the running shell works only if the shell was invoked through the $PATH and the $PATH hasn't changed, or through an absolute path.
Here's another method in zsh which is slightly clearer but longer:
sudo zsh -c $history[$[HISTCMD-1]]
A final word of warning: sudo
is for potentially dangerous commands. Don't make it too easy to use it!
¹ There's some extra whitespace at the beginning and the command substitution strips off newlines at the end, but the syntax of the shell doesn't care about that.
² I don't think zsh or ksh have anything like bash's $BASH
; $0
only works when it's an absolute path, or when it contains no slash and the command search path hasn't changed.
³ fc
is an alias for hist
in ATT ksh but that's just as good.
Solution 2
If you want to redo the same command with sudo !! after doing a command like this:
echo "something">/path/file
The you use the global replace syntax to recall the command :
!!:gs/>/|sudo tee -a /
Use a space after the -a parameter.
This is the equivalent to sudo !! but helps you bypass sudo restrictions for the < and >. Because sudo does not allow you to use [<, >].
To bypass sudo restrictions in general for redirections you can use it like this:
echo "something" | sudo tee myfile
tee command will allow you to read from standard input and write to standard output and files
If you want to repeat the command and append a text to the file, the tee command has the -a option for appending. So you could recall the command with
sudo !!
and the text will be appended in the file
example:
echo "something" | sudo tee -a /path/file
sudo !!
Solution 3
It seems to be as simple as sudo sh -c "!!"
:
$ cd /
$ echo hello > foo
bash: foo: Permission denied
$ sudo sh -c "!!"
sudo sh -c "echo hello > foo"
$ ls -l foo
-rw-r--r-- 1 root root 6 Jun 20 16:21 foo
Related videos on Youtube
Comments
-
rubo77 almost 2 years
For example if I want to create a file and enter text in one line I can redirect the output into a file with the use of the
>
operator:echo "something" > /path/foobar
but if I don't have access to the folder
/path/
and need sudo priviledges, How can I achieve this same command as a normal user with sudo rights?I tried
sudo echo "something" > /path/foobar
but that doesn't work, because the sudo only counts for the
edit
but not for the right part
of the>
Sure, I could become root before with
sudo su
or usetee
instead:echo "something" | sudo tee /path/foobar
But I would like to find a solution where I can work with the last line as replacement via
sudo !!
Isn't there a way to "recycle" the last line and just add
sudo
in front?-
goldilocks about 10 yearspossible duplicate of Redirecting stdout to a file you don't have write permission on
-
rubo77 about 10 yearsThis is not a duplicate. I extracted the real Qeustion and changed the title. Now it is what I am really looking for
-
goldilocks about 10 yearsIt certainly was a duplicate, but it is somewhat different now. It looks to me like you rewrote the question in light of Boogy's answer, which is fine -- that is a good answer. I've retracted my close vote, but it is still inevitable (people often vote automatically once a question is in the close queue without paying attention to the issue): address a comment @goldilocks when it gets closed and I'll vote to reopen. You can also plead your case in chat once that happens.
-
Gilles 'SO- stop being evil' about 10 yearsSee also How can I
alias sudo !!
?
-
-
rubo77 about 10 yearsnice solution, but a bit hard to memorize. How can I create an alias for a command using !! to recall the last command?
-
godlygeek about 10 yearsIf the command used quotes, this isn't necessarily equivalent. Consider
echo "foo bar"
which would becomesh -c "echo "foo bar""
which would just printfoo
instead offoo bar
. -
rubo77 about 10 yearsis the
-a
really needed?>
will overwrite a file,tee -a
will append, which would be>>
-
rubo77 about 10 yearsI tried
sudo sh -c '!!'
instead if your command but that doesn't work either -
godlygeek about 10 yearsThen what if your command used both single and double quotes? Or double quotes and variable expansions? If the user did:
a=b
and thenecho "$a" >file
and thensudo sh -c '!!'
it would expand tosudo sh -c 'echo $a >file'
which would print an empty line instead ofb
intofile
. -
rubo77 about 10 yearsSo maybe there is an even better solution somehow?
-
godlygeek about 10 yearsI don't think there's any solution that will work 100% of the time without you ever needing to modify the command. Using
sudo
to get a root shell and then copying and pasting the command into it would be closest, but fails if the command was expected to use variables that were set in your non-root shell. Usingsudo sh -c "!!"
works fine for simple commands, but is fraught for complex ones. I think that the best advice is to not expect that there is some command that will work 100% of the time - learn some possible solutions and apply each when it best fits.