How can I get super-user privilege within vi? [duplicate] - linux

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does the vim “write with sudo” trick work?
This situation always happen: I try to vi a configuration file but I forget to add sudo before it, and when I try to save it, vi prompt me that this file is read only.
How can I change to super-user privilege without get out of vi and re-edit that file?

This works for me in vi and vim:
:w !sudo tee %

cmap w!! %!sudo tee > /dev/null %
Add the line in ~ /. Vimrc and do: w!! to keep with sudo

Usually I save it in temp with :w /tmp/foo.txt and then sudo cp.

Related

Saving a file opened without admin permissions [duplicate]

Many of you have probably seen the command that allows you to write on a file that needs root permission, even when you forgot to open vim with sudo:
:w !sudo tee %
The thing is that I don't get what is exactly happening here.
I have already figured this:
w is for this
*:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
Execute {cmd} with [range] lines as standard input
(note the space in front of the '!'). {cmd} is
executed like with ":!{cmd}", any '!' is replaced with
the previous command |:!|.
so it passes all the lines as standard input.
The !sudo tee part calls tee with administrator privileges.
For all to make sense, the % should output the filename (as a parameter for tee), but I can't find references on the help for this behavior.
tl;dr Could someone help me dissect this command?
In :w !sudo tee %...
% means "the current file"
As eugene y pointed out, % does indeed mean "the current file name", which is passed to tee so that it knows which file to overwrite.
(In substitution commands, it's slightly different; as :help :% shows, it's equal to 1,$ (the entire file) (thanks to #Orafu for pointing out that this does not evaluate to the filename). For example, :%s/foo/bar means "in the current file, replace occurrences of foo with bar." If you highlight some text before typing :s, you'll see that the highlighted lines take the place of % as your substitution range.)
:w isn't updating your file
One confusing part of this trick is that you might think :w is modifying your file, but it isn't. If you opened and modified file1.txt, then ran :w file2.txt, it would be a "save as"; file1.txt wouldn't be modified, but the current buffer contents would be sent to file2.txt.
Instead of file2.txt, you can substitute a shell command to receive the buffer contents. For instance, :w !cat will just display the contents.
If Vim wasn't run with sudo access, its :w can't modify a protected file, but if it passes the buffer contents to the shell, a command in the shell can be run with sudo. In this case, we use tee.
Understanding tee
As for tee, picture the tee command as a T-shaped pipe in a normal bash piping situation: it directs output to specified file(s) and also sends it to standard output, which can be captured by the next piped command.
For example, in ps -ax | tee processes.txt | grep 'foo', the list of processes will be written to a text file and passed along to grep.
+-----------+ tee +------------+
| | -------- | |
| ps -ax | -------- | grep 'foo' |
| | || | |
+-----------+ || +------------+
||
+---------------+
| |
| processes.txt |
| |
+---------------+
(Diagram created with Asciiflow.)
See the tee man page for more info.
Tee as a hack
In the situation your question describes, using tee is a hack because we're ignoring half of what it does. sudo tee writes to our file and also sends the buffer contents to standard output, but we ignore standard output. We don't need to pass anything to another piped command in this case; we're just using tee as an alternate way of writing a file and so that we can call it with sudo.
Making this trick easy
You can add this to your .vimrc to make this trick easy-to-use: just type :w!!.
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %
The > /dev/null part explicitly throws away the standard output, since, as I said, we don't need to pass anything to another piped command.
In the executed command line, % stands for the current file name. This is documented in :help cmdline-special:
In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
% Is replaced with the current file name.
As you've already found out, :w !cmd pipes the contents of the current buffer to another command. What tee does is copy standard input to one or more files, and also to standard output. Therefore, :w !sudo tee % > /dev/null effectively writes the contents of the current buffer to the current file while being root. Another command that can be used for this is dd:
:w !sudo dd of=% > /dev/null
As a shortcut, you can add this mapping to your .vimrc:
" Force saving files that require root permission
cnoremap w!! w !sudo tee > /dev/null %
With the above you can type :w!!<Enter> to save the file as root.
The accepted answer covers it all, so I'll just give another example of a shortcut that I use, for the record.
Add it to your etc/vim/vimrc (or ~/.vimrc):
cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
Where:
cnoremap: tells vim that the following shortcut is to be associated in the command line.
w!!: the shortcut itself.
execute '...': a command that execute the following string.
silent!: run it silently
write !sudo tee % >/dev/null: the OP question, added a redirection of messages to NULL to make a clean command
<bar> edit!: this trick is the cherry of the cake: it calls also the edit command to reload the buffer and then avoid messages such as the buffer has changed. <bar> is how to write the pipe symbol to separate two commands here.
Hope it helps. See also for other problems:
SuperUser: force vim to write a file
This also works well:
:w !sudo sh -c "cat > %"
This is inspired by the comment of #Nathan Long.
NOTICE:
" must be used instead of ' because we want % to be expanded before passing to shell.
:w - Write a file.
!sudo - Call shell sudo command.
tee - The output of write (vim :w) command redirected using tee. The % is nothing but current file name i.e. /etc/apache2/conf.d/mediawiki.conf. In other words tee command is run as root and it takes standard input and write it to a file represented by %. However, this will prompt to reload file again (hit L to load changes in vim itself):
tutorial link
I'd like to suggest another approach to the "Oups I forgot to write sudo while opening my file" issue:
Instead of receiving a permission denied, and having to type :w!!, I find it more elegant to have a conditional vim command that does sudo vim if file owner is root.
This is as easy to implement (there might even be more elegant implementations, I'm clearly not a bash-guru):
function vim(){
OWNER=$(stat -c '%U' $1)
if [[ "$OWNER" == "root" ]]; then
sudo /usr/bin/vim $*;
else
/usr/bin/vim $*;
fi
}
And it works really well.
This is a more bash-centered approach than a vim-one so not everybody might like it.
Of course:
there are use cases where it will fail (when file owner is not root but requires sudo, but the function can be edited anyway)
it doesn't make sense when using vim for reading-only a file (as far as I'm concerned, I use tail or cat for small files)
But I find this brings a much better dev user experience, which is something that IMHO tends to be forgotten when using bash. :-)
FOR NEOVIM
Due to problems with interactive calls (https://github.com/neovim/neovim/issues/1716), I am using this for neovim, based on Dr Beco's answer:
cnoremap w!! execute 'silent! write !SUDO_ASKPASS=`which ssh-askpass` sudo tee % >/dev/null' <bar> edit!
This will open a dialog using ssh-askpass asking for the sudo password.
A summary (and very minor improvement) on the most common answers that I found for this as at 2020.
tl;dr
Call with :w!! or :W!!.
After it expands, press enter.
If you are too slow in typing the !! after the w/W, it will not expand and might report: E492: Not an editor command: W!!
NOTE Use which tee output to replace /usr/bin/tee if it differs in your case.
Put these in your ~/.vimrc file:
" Silent version of the super user edit, sudo tee trick.
cnoremap W!! execute 'silent! write !sudo /usr/bin/tee "%" >/dev/null' <bar> edit!
" Talkative version of the super user edit, sudo tee trick.
cmap w!! w !sudo /usr/bin/tee >/dev/null "%"
More Info:
First, the linked answer below was about the only other that seemed to mitigate most known problems and differ in any significant way from the others. Worth reading:
https://stackoverflow.com/a/12870763/2927555
My answer above was pulled together from multiple suggestions on the conventional sudo tee theme and thus very slightly improves on the most common answers I found. My version above:
Works with whitespace in file names
Mitigates path modification attacks by specifying the full path to tee.
Gives you two mappings, W!! for silent execution, and w!! for not silent, i.e Talkative :-)
The difference in using the non-silent version is that you get to choose between [O]k and [L]oad. If you don't care, use the silent version.
[O]k - Preserves your undo history, but will cause you to get warned when you try to quit. You have to use :q! to quit.
[L]oad - Erases your undo history and resets the "modified flag" allowing you to exit without being warned to save changes.
Information for the above was drawn from a bunch of other answers and comments on this, but notably:
Dr Beco's answer: https://stackoverflow.com/a/48237738/2927555
idbrii's comment to this: https://stackoverflow.com/a/25010815/2927555
Han Seoul-Oh's comment to this: How does the vim "write with sudo" trick work?
Bruno Bronosky comment to this: https://serverfault.com/a/22576/195239
This answer also explains why the apparently most simple approach is not such a good idea:
https://serverfault.com/a/26334/195239
The only problem with cnoremap w!! is that it replaces w with ! (and hangs until you type the next char) whenever you type w! at the : command prompt. Like when you want to actually force-save with w!. Also, even if it's not the first thing after :.
Therefore I would suggest mapping it to something like <Fn>w. I personally have mapleader = F1, so I'm using <Leader>w.

Change file permissions in Vim with open file

I vim somefile.txt often without using sudo. Is it possible to use sudo within an open vim session so you don't have to close the file and reopen? New to Vim and Linux in general so any help is very appreciated. Thank you.
Well seems like I was late to the party. As said you should use :w !sudo tee % to switch to sudo. If you would like to change the permissions of the file so you will not need sudo again you could use :!chmod +w % in command mode with %getting replaced by the filename to change the permissions of the file afterwards, as stated here: How to change file permission from within vi.
I have this in my .vimrc, so that a :W will write with sudo access.
" :W sudo saves the file
command W w !sudo tee % > /dev/null`
You can use the SudoEdit plugin; it provides a :SudoWrite command.
There's also a trick of :write to a process of !sudo tee, passing the current file name; it is explained here.

adding a shell script to a configuration file

I'm pretty new to shell scripting and linux in general. Basically, I need to change the configuration file for logging out so that when a user logs out, a certain shell script is run.
Now, I've located the logout configuration file and opened it with vi using this command
$ vi ~/.bash_logout
At this point, I'm experiencing some very weird behavior. When I try to type a character, the cursor jumps around seemingly erratically. What could this be due to? I'm running the latest version of ubuntu.
And once I get that figured out, what's the command to run a .sh file from within this configuration file?
If you're having trouble with vi, try using nano instead. nano .bash_logout
If you do need to use vi for some reason, "i" will put the editor into insert mode, and ESC will take it out of insert mode when you're done. ":wq" will write and quit the editor.
To run a command, just put it in the .bash_logout file as you would type it on the commandline.
Some other useful commands:
a insert after selected character
o insert at next line
O insert at previous line
r replace a single character
R replace mode
:q! quit without saving
:w save
:wq save and quit
To get familiar with Vi and its brother Vim ("VI improved") I recommend the book "A Byte of Vim", you can read it online or download for free at http://www.swaroopch.com/notes/Vim
You can permanently change your editor option. To find out what your current one is, type this:
export | grep -i edit
To change it on Ubuntu:
sudo update-alternatives –config editor
On any other BASH prompt, just do this:
export EDITOR="nano"
Replace 'nano' with 'vi', 'emacs', or any other preferred editor. You can also add this to your .bashrc by typing the following:
echo 'EDITOR="nano"' >> ~/.bashrc

How does the vim "write with sudo" trick work?

Many of you have probably seen the command that allows you to write on a file that needs root permission, even when you forgot to open vim with sudo:
:w !sudo tee %
The thing is that I don't get what is exactly happening here.
I have already figured this:
w is for this
*:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
Execute {cmd} with [range] lines as standard input
(note the space in front of the '!'). {cmd} is
executed like with ":!{cmd}", any '!' is replaced with
the previous command |:!|.
so it passes all the lines as standard input.
The !sudo tee part calls tee with administrator privileges.
For all to make sense, the % should output the filename (as a parameter for tee), but I can't find references on the help for this behavior.
tl;dr Could someone help me dissect this command?
In :w !sudo tee %...
% means "the current file"
As eugene y pointed out, % does indeed mean "the current file name", which is passed to tee so that it knows which file to overwrite.
(In substitution commands, it's slightly different; as :help :% shows, it's equal to 1,$ (the entire file) (thanks to #Orafu for pointing out that this does not evaluate to the filename). For example, :%s/foo/bar means "in the current file, replace occurrences of foo with bar." If you highlight some text before typing :s, you'll see that the highlighted lines take the place of % as your substitution range.)
:w isn't updating your file
One confusing part of this trick is that you might think :w is modifying your file, but it isn't. If you opened and modified file1.txt, then ran :w file2.txt, it would be a "save as"; file1.txt wouldn't be modified, but the current buffer contents would be sent to file2.txt.
Instead of file2.txt, you can substitute a shell command to receive the buffer contents. For instance, :w !cat will just display the contents.
If Vim wasn't run with sudo access, its :w can't modify a protected file, but if it passes the buffer contents to the shell, a command in the shell can be run with sudo. In this case, we use tee.
Understanding tee
As for tee, picture the tee command as a T-shaped pipe in a normal bash piping situation: it directs output to specified file(s) and also sends it to standard output, which can be captured by the next piped command.
For example, in ps -ax | tee processes.txt | grep 'foo', the list of processes will be written to a text file and passed along to grep.
+-----------+ tee +------------+
| | -------- | |
| ps -ax | -------- | grep 'foo' |
| | || | |
+-----------+ || +------------+
||
+---------------+
| |
| processes.txt |
| |
+---------------+
(Diagram created with Asciiflow.)
See the tee man page for more info.
Tee as a hack
In the situation your question describes, using tee is a hack because we're ignoring half of what it does. sudo tee writes to our file and also sends the buffer contents to standard output, but we ignore standard output. We don't need to pass anything to another piped command in this case; we're just using tee as an alternate way of writing a file and so that we can call it with sudo.
Making this trick easy
You can add this to your .vimrc to make this trick easy-to-use: just type :w!!.
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %
The > /dev/null part explicitly throws away the standard output, since, as I said, we don't need to pass anything to another piped command.
In the executed command line, % stands for the current file name. This is documented in :help cmdline-special:
In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
% Is replaced with the current file name.
As you've already found out, :w !cmd pipes the contents of the current buffer to another command. What tee does is copy standard input to one or more files, and also to standard output. Therefore, :w !sudo tee % > /dev/null effectively writes the contents of the current buffer to the current file while being root. Another command that can be used for this is dd:
:w !sudo dd of=% > /dev/null
As a shortcut, you can add this mapping to your .vimrc:
" Force saving files that require root permission
cnoremap w!! w !sudo tee > /dev/null %
With the above you can type :w!!<Enter> to save the file as root.
The accepted answer covers it all, so I'll just give another example of a shortcut that I use, for the record.
Add it to your etc/vim/vimrc (or ~/.vimrc):
cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
Where:
cnoremap: tells vim that the following shortcut is to be associated in the command line.
w!!: the shortcut itself.
execute '...': a command that execute the following string.
silent!: run it silently
write !sudo tee % >/dev/null: the OP question, added a redirection of messages to NULL to make a clean command
<bar> edit!: this trick is the cherry of the cake: it calls also the edit command to reload the buffer and then avoid messages such as the buffer has changed. <bar> is how to write the pipe symbol to separate two commands here.
Hope it helps. See also for other problems:
SuperUser: force vim to write a file
This also works well:
:w !sudo sh -c "cat > %"
This is inspired by the comment of #Nathan Long.
NOTICE:
" must be used instead of ' because we want % to be expanded before passing to shell.
:w - Write a file.
!sudo - Call shell sudo command.
tee - The output of write (vim :w) command redirected using tee. The % is nothing but current file name i.e. /etc/apache2/conf.d/mediawiki.conf. In other words tee command is run as root and it takes standard input and write it to a file represented by %. However, this will prompt to reload file again (hit L to load changes in vim itself):
tutorial link
I'd like to suggest another approach to the "Oups I forgot to write sudo while opening my file" issue:
Instead of receiving a permission denied, and having to type :w!!, I find it more elegant to have a conditional vim command that does sudo vim if file owner is root.
This is as easy to implement (there might even be more elegant implementations, I'm clearly not a bash-guru):
function vim(){
OWNER=$(stat -c '%U' $1)
if [[ "$OWNER" == "root" ]]; then
sudo /usr/bin/vim $*;
else
/usr/bin/vim $*;
fi
}
And it works really well.
This is a more bash-centered approach than a vim-one so not everybody might like it.
Of course:
there are use cases where it will fail (when file owner is not root but requires sudo, but the function can be edited anyway)
it doesn't make sense when using vim for reading-only a file (as far as I'm concerned, I use tail or cat for small files)
But I find this brings a much better dev user experience, which is something that IMHO tends to be forgotten when using bash. :-)
FOR NEOVIM
Due to problems with interactive calls (https://github.com/neovim/neovim/issues/1716), I am using this for neovim, based on Dr Beco's answer:
cnoremap w!! execute 'silent! write !SUDO_ASKPASS=`which ssh-askpass` sudo tee % >/dev/null' <bar> edit!
This will open a dialog using ssh-askpass asking for the sudo password.
A summary (and very minor improvement) on the most common answers that I found for this as at 2020.
tl;dr
Call with :w!! or :W!!.
After it expands, press enter.
If you are too slow in typing the !! after the w/W, it will not expand and might report: E492: Not an editor command: W!!
NOTE Use which tee output to replace /usr/bin/tee if it differs in your case.
Put these in your ~/.vimrc file:
" Silent version of the super user edit, sudo tee trick.
cnoremap W!! execute 'silent! write !sudo /usr/bin/tee "%" >/dev/null' <bar> edit!
" Talkative version of the super user edit, sudo tee trick.
cmap w!! w !sudo /usr/bin/tee >/dev/null "%"
More Info:
First, the linked answer below was about the only other that seemed to mitigate most known problems and differ in any significant way from the others. Worth reading:
https://stackoverflow.com/a/12870763/2927555
My answer above was pulled together from multiple suggestions on the conventional sudo tee theme and thus very slightly improves on the most common answers I found. My version above:
Works with whitespace in file names
Mitigates path modification attacks by specifying the full path to tee.
Gives you two mappings, W!! for silent execution, and w!! for not silent, i.e Talkative :-)
The difference in using the non-silent version is that you get to choose between [O]k and [L]oad. If you don't care, use the silent version.
[O]k - Preserves your undo history, but will cause you to get warned when you try to quit. You have to use :q! to quit.
[L]oad - Erases your undo history and resets the "modified flag" allowing you to exit without being warned to save changes.
Information for the above was drawn from a bunch of other answers and comments on this, but notably:
Dr Beco's answer: https://stackoverflow.com/a/48237738/2927555
idbrii's comment to this: https://stackoverflow.com/a/25010815/2927555
Han Seoul-Oh's comment to this: How does the vim "write with sudo" trick work?
Bruno Bronosky comment to this: https://serverfault.com/a/22576/195239
This answer also explains why the apparently most simple approach is not such a good idea:
https://serverfault.com/a/26334/195239
The only problem with cnoremap w!! is that it replaces w with ! (and hangs until you type the next char) whenever you type w! at the : command prompt. Like when you want to actually force-save with w!. Also, even if it's not the first thing after :.
Therefore I would suggest mapping it to something like <Fn>w. I personally have mapleader = F1, so I'm using <Leader>w.

How do you get sudo access for a file inside the vi text editor? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 3 years ago.
Improve this question
Often while editing config files, I'll open one with vi and then when I go to save it realize that I didn't type
sudo vi filename
Is there any way to give vi sudo privileges to save the file? I seem to recall seeing something about this while looking up some stuff about vi a while ago, but now I can't find it.
% is replaced with the current file name, thus you can use:
:w !sudo tee %
(vim will detect that the file has been changed and ask whether you want to it to be reloaded. Say yes by choosing [L] rather than OK.)
As a shortcut, you can define your own command. Put the following in your .vimrc:
command W w !sudo tee % >/dev/null
With the above you can type :W<Enter> to save the file. Since I wrote this, I have found a nicer way (in my opinion) to do this:
cmap w!! w !sudo tee >/dev/null %
This way you can type :w!! and it will be expanded to the full command line, leaving the cursor at the end, so you can replace the % with a file name of your own, if you like.
In general, you can't change the effective user id of the vi process, but you can do this:
:w !sudo tee myfile
Common Caveats
The most common method of getting around the read-only file problem is to open a pipe to current file as the super-user using an implementation of sudo tee. However, all of the most popular solutions that I have found around the Internet have a combination of a several potential caveats:
The entire file gets written to the terminal, as well as the file. This can be slow for large files, especially over slow network connections.
The file loses its modes and similar attributes.
File paths with unusual characters or spaces might not be handled correctly.
Solutions
To get around all of these issues, you can use the following command:
" On POSIX (Linux/Mac/BSD):
:silent execute 'write !sudo tee ' . shellescape(#%, 1) . ' >/dev/null'
" Depending on the implementation, you might need this on Windows:
:silent execute 'write !sudo tee ' . shellescape(#%, 1) . ' >NUL'
These can be shortened, respectfully:
:sil exec 'w !sudo tee ' . shellescape(#%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(#%, 1) . ' >NUL'
Explanation
: begins the command; you will need to type this character in normal mode to start entering a command. It should be omitted in scripts.
sil[ent] suppresses output from the command. In this case, we want to stop the Press any key to continue-like prompt that appears after running the :! command.
exec[ute] executes a string as a command. We can't just run :write because it won't process the necessary function call.
! represents the :! command: the only command that :write accepts. Normally, :write accepts a file path to which to write. :! on its own runs a command in a shell (for example, using bash -c). With :write, it will run the command in the shell, and then write the entire file to stdin.
sudo should be obvious, since that's why you're here. Run the command as the super-user. There's plenty of information around the 'net about how that works.
tee pipes stdin to the given file. :write will write to stdin, then the super-user tee will receive the file contents and write the file. It won't create a new file--just overwrite the contents--so file modes and attributes will be preserved.
shellescape() escapes special characters in the given file path as appropriate for the current shell. With just one parameter, it would typically just enclose the path in quotes as necessary. Since we're sending to a full shell command line, we'll want to pass a non-zero value as the second argument to enable backslash-escaping of other special characters that might otherwise trip up the shell.
#% reads the contents of the % register, which contains the current buffer's file name. It's not necessarily an absolute path, so ensure that you haven't changed the current directory. In some solutions, you will see the commercial-at symbol omitted. Depending on the location, % is a valid expression, and has the same effect as reading the % register. Nested inside another expression the shortcut is generally disallowed, however: such as in this case.
>NUL and >/dev/null redirect stdout to the platform's null device. Even though we've silenced the command, we don't want all of the overhead associated with piping stdin back to vim--best to dump it as early as possible. NUL is the null device on DOS, MS-DOS, and Windows, not a valid file. As of Windows 8 redirections to NUL don't result in a file named NUL being written. Try creating a file on your desktop named NUL, with or without a file extension: you will be unable to do so. (There are several other device names in Windows that might be worth getting to know.)
~/.vimrc
Platform-Dependent
Of course, you still don't want to memorize those and type them out each time. It's much easier to map the appropriate command to a simpler user command. To do this on POSIX, you could add the following line to your ~/.vimrc file, creating it if it doesn't already exist:
command W silent execute 'write !sudo tee ' . shellescape(#%, 1) . ' >/dev/null'
This will allow you to type the :W (case-sensitive) command to write the current file with super-user permissions--much easier.
Platform-Independent
I use a platform-independent ~/.vimrc file that synchronizes across computers, so I added multi-platform functionality to mine. Here's a ~/.vimrc with only the relevant settings:
#!vim
" Use za (not a command; the keys) in normal mode to toggle a fold.
" META_COMMENT Modeline Definition: {{{1
" vim: ts=4 sw=4 sr sts=4 fdm=marker ff=unix fenc=utf-8
" ts: Actual tab character stops.
" sw: Indentation commands shift by this much.
" sr: Round existing indentation when using shift commands.
" sts: Virtual tab stops while using tab key.
" fdm: Folds are manually defined in file syntax.
" ff: Line endings should always be <NL> (line feed #09).
" fenc: Should always be UTF-8; #! must be first bytes, so no BOM.
" General Commands: User Ex commands. {{{1
command W call WriteAsSuperUser(#%) " Write file as super-user.
" Helper Functions: Used by user Ex commands. {{{1
function GetNullDevice() " Gets the path to the null device. {{{2
if filewritable('/dev/null')
return '/dev/null'
else
return 'NUL'
endif
endfunction
function WriteAsSuperUser(file) " Write buffer to a:file as the super user (on POSIX, root). {{{2
exec '%write !sudo tee ' . shellescape(a:file, 1) . ' >' . GetNullDevice()
endfunction
" }}}1
" EOF
If you're using Vim, there is a script available named sudo.vim. If you find that you've opened a file that you need root access to read, type:e sudo:%Vim replaces the % with the name of the current file, and sudo: instructs the sudo.vim script to take over for reading and writing.
Ryan's advice is generally good, however, if following step 3, don't move the temporary file; it'll have the wrong ownership and permissions. Instead, sudoedit the correct file and read in the contents (using :r or the like) of the temporary file.
If following step 2, use :w! to force the file to be written.
When you go into insert mode on a file you need sudo access to edit, you get a status message saying
-- INSERT -- W10: Warning: Changing a readonly file
If I miss that, generally I do
:w ~/edited_blah.tmp
:q
..then..
sudo "cat edited_blah.tmp > /etc/blah"
..or..
sudo mv edited_blah.tmp /etc/blah
There's probably a less roundabout way to do it, but it works.
A quick Google seems to give this advice:
Don't try to edit if it's read-only.
You might be able to change the permissions on the file. (Whether or not it will let you save is up to experimentation.)
If you still edited anyway, save to a temporary file and then move it.
http://ubuntuforums.org/showthread.php?t=782136
Here's another one that has appeared since this question was answered, a plugin called SudoEdit which provides SudoRead and SudoWrite functions, which will by default try to use sudo first and su if that fails: http://www.vim.org/scripts/script.php?script_id=2709
I have this in my ~/.bashrc:
alias svim='sudo vim'
Now whenever I need to edit a config file I just open it with svim.
A quick hack you can consider is doing a chmod on the file you're editing, save with vim, and then chmod back to what the file was originally.
ls -l test.file (to see the permissions of the file)
chmod 777 test.file
[This is where you save in vim]
chmod xxx test.file (restore the permissions you found in the first step)
Of course I don't recommend this approach in a system where you're worried about security, as for a few seconds anyone can read/change the file without you realizing.

Resources