No edit summary |
JohnBeckett (talk | contribs) Tag: Source edit |
||
(11 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
+ | {{TipImported |
||
− | {{review}} |
||
− | {{Tip |
||
|id=975 |
|id=975 |
||
+ | |previous=974 |
||
− | |title=su-write |
||
+ | |next=976 |
||
− | |created= |
+ | |created=2005 |
|complexity=basic |
|complexity=basic |
||
|author=Bernard Pratz |
|author=Bernard Pratz |
||
|version=6.0 |
|version=6.0 |
||
|rating=7/3 |
|rating=7/3 |
||
+ | |category1= |
||
− | |text= |
||
+ | |category2= |
||
− | I just wrote a little function that uses sudo and cp to save a file whose modes wouldn't allow me to write it. |
||
− | |||
− | Obviously, it preserves the modes of the original file, though it is being rewrited. Of course, this tip has to |
||
− | |||
⚫ | |||
− | |||
− | |||
− | |||
− | TODO: |
||
− | |||
− | The only real drawback is there's no check for symlinks, and then, the symlink would get removed and |
||
− | |||
⚫ | |||
− | |||
− | Another thing that would be nice, would be to integrate it to the interface, to get it work when :w is not |
||
− | |||
− | enough, or at least having an alias like :wforce, :w!! or :whatever... |
||
− | |||
− | |||
− | |||
⚫ | |||
− | |||
⚫ | |||
− | |||
− | exe 'w '.fname |
||
− | |||
− | let modes=system('find . -maxdepth 1 -name '.expand("%").' -printf "%m"') |
||
− | |||
− | exec '!sudo cp '.fname.' '.expand("%") |
||
− | |||
− | exec '!sudo chmod '.modes." ".expand("%") |
||
− | |||
− | } |
||
− | |||
− | |||
}} |
}} |
||
+ | Sometimes you modify a file, for example from the <code>/etc</code> directory, then when you try to save the file, you get a permission-denied error. This tip presents some suggestions for using sudo from with Vim, so you can successfullly write the file with temporary privileges. |
||
⚫ | |||
⚫ | |||
− | just use : |
||
− | system('stat -c%a '.expand("%")) |
||
− | instead of |
||
− | system('find . -maxdepth 1 -name '.expand("%").' -printf "%m"') |
||
+ | ==Suggestion 1== |
||
− | useless use of find O:-) |
||
+ | If you find you do not have permission to perform <code>:w</code>, use the following: |
||
− | thanks to strull for the clever suggestion |
||
+ | <pre> |
||
⚫ | |||
+ | </pre> |
||
+ | You can make a command so <code>:W</code> invokes sudo: |
||
− | -- |
||
+ | <pre> |
||
− | Guyzmo |
||
⚫ | |||
+ | </pre> |
||
+ | Or, if you know about the problem beforehand: |
||
− | bernardATpratzDOTnet |
||
+ | <pre> |
||
− | , August 18, 2005 17:20 |
||
+ | sudoedit path_to_file |
||
− | ---- |
||
+ | sudo -e path_to_file |
||
− | I just forgot a detail, to restore the user/group of the original file : |
||
+ | </pre> |
||
− | |||
− | function Suedit() |
||
− | let fname=tempname() |
||
− | exe 'w '.fname |
||
⚫ | |||
⚫ | |||
− | exec '!sudo cp '.fname.' '.expand("%") |
||
− | exec '!sudo chmod '.modes." ".expand("%") |
||
⚫ | |||
⚫ | |||
− | |||
− | this time, I hope it'll work correctly |
||
− | |||
− | -- |
||
− | Guyzmo |
||
− | (going to bed) |
||
− | |||
− | bernardATpratzDOTnet |
||
− | , August 18, 2005 17:26 |
||
− | ---- |
||
− | I have made no tests on this script, that should work as is... When I'll have time, I'll make a script around |
||
− | that to check for all errors, with confirmation and all that stuff, and be free to do it before me, if you got the |
||
− | time to do so :P |
||
− | |||
− | -- |
||
− | Guyzmo |
||
− | |||
− | bernardATpratzDOTnet |
||
− | , August 18, 2005 17:36 |
||
− | ---- |
||
− | Spare yourself the effort: [/scripts/script.php?script_id=729 vimscript #729] already does this. |
||
− | |||
− | pagaltzis--AT--gmx.de |
||
− | , August 18, 2005 20:46 |
||
− | ---- |
||
− | Except when the system lacks sudo. (forex: vanilla FreeBSD and OpenBSD installs) |
||
− | |||
− | |||
− | foltiATbalabitDOThu |
||
− | , August 19, 2005 3:58 |
||
− | ---- |
||
− | What's your point? Of course you can't use permissions granted via sudo if you don't have sudo. |
||
− | |||
− | pagaltzis--AT--gmx.de |
||
− | , August 19, 2005 5:40 |
||
− | ---- |
||
− | Why is sudo dragged into vim, use the shell. |
||
− | |||
− | Jake |
||
− | , August 19, 2005 15:15 |
||
− | ---- |
||
− | For the same reason that wget or scp or rsync have been dragged into Vim? |
||
− | |||
− | pagaltzis--AT--gmx.de |
||
− | , August 20, 2005 3:47 |
||
− | ---- |
||
− | :w !sudo tee % |
||
− | |||
− | It's very simple. |
||
− | |||
− | gorou |
||
− | , August 23, 2005 22:40 |
||
− | ---- |
||
− | > :w !sudo tee % |
||
− | > It's very simple. |
||
− | |||
− | ... and quite clever! ;-) |
||
− | |||
− | Minor improvement to prevent tee's stdout from "cluttering" your vim session: |
||
− | |||
⚫ | |||
− | |||
− | But Jake makes a good point, though: why not just: |
||
− | |||
− | sudo vi <file_whose_modes_wouldn't_allow_me_to_write_it> |
||
− | |||
− | Or, if you don't want to run your entire vim sesion as sudo: |
||
− | |||
− | [/scripts/script.php?script_id=729 vimscript #729] : sudo.vim |
||
− | |||
− | Peter Vandenberk |
||
− | |||
− | |||
− | pvdbp--AT--yahoo.co.uk |
||
− | , August 24, 2005 3:51 |
||
− | ---- |
||
⚫ | |||
+ | ==Suggestion 2== |
||
− | Is BRILLIANT! |
||
+ | The following function saves the current file to a temporary file, then copies the new file to replace the original. It preserves the modes of the original file, though it is being rewritten. |
||
+ | <pre> |
||
⚫ | |||
⚫ | |||
+ | exec 'w' fname |
||
+ | let writetarget=shellescape(expand("%:p")) |
||
⚫ | |||
⚫ | |||
+ | exec '!sudo cp' shellescape(fname) writetarget |
||
+ | exec '!sudo chmod' modes writetarget |
||
⚫ | |||
⚫ | |||
+ | </pre> |
||
⚫ | |||
− | [quote] |
||
− | But Jake makes a good point, though: why not just: |
||
+ | ==Suggestion 3== |
||
− | sudo vi <file_whose_modes_wouldn't_allow_me_to_write_it> |
||
+ | Here is a mapping to save to a <code>/tmp</code> file, then overwrite the working file. |
||
+ | <pre> |
||
+ | nnoremap <leader>es :w! /tmp/sudoSave \| let $fileToSave=expand('%') \| let $fileToSaveBackup=expand('%').'~' \| !sudo cp $fileToSave $fileToSaveBackup && sudo cp /tmp/sudoSave $fileToSave<CR><ESC>:e!<CR> |
||
+ | </pre> |
||
+ | '''Warning''' This command will reload the file; you will lose the modifications history (undo will not work, although it does keep a backup). |
||
− | Peter Vandenberk |
||
− | [/quote] |
||
+ | Note that a backup is made, even when '<code>nobackup</code>' is set. |
||
− | Peter, |
||
− | I often forget to open a file as sudo, or open a file expecting to only view it, and then find a problem with it. This saves me from having to: |
||
− | :w /tmp/% |
||
− | Then sudo mv the file in place after I exit. I love it! |
||
⚫ | |||
− | I also try to learn to do things without plugin and custom mappings so that I can use it on any system. I use hundreds of servers and rarely have access to my .vimrc |
||
+ | Use {{script|id=729}} which has had more testing or use {{script|id=2709}} which is an improved version of the first plugin (since it is not developed any more). |
||
− | RichardBronosky (first--AT--last.com) |
||
− | , July 12, 2006 8:02 |
||
---- |
---- |
||
− | <!-- parsed by vimtips.py in 0.686125 seconds--> |
Latest revision as of 03:43, 22 May 2021
created 2005 · complexity basic · author Bernard Pratz · version 6.0
Sometimes you modify a file, for example from the /etc
directory, then when you try to save the file, you get a permission-denied error. This tip presents some suggestions for using sudo from with Vim, so you can successfullly write the file with temporary privileges.
Of course, this tip has to be used with caution, as it gets you more power.
Suggestion 1[]
If you find you do not have permission to perform :w
, use the following:
:w !sudo tee "%" > /dev/null
You can make a command so :W
invokes sudo:
command W w !sudo tee "%" > /dev/null
Or, if you know about the problem beforehand:
sudoedit path_to_file sudo -e path_to_file
Suggestion 2[]
The following function saves the current file to a temporary file, then copies the new file to replace the original. It preserves the modes of the original file, though it is being rewritten.
function Suedit() let fname=tempname() exec 'w' fname let writetarget=shellescape(expand("%:p")) let owner=shellescape(system('stat --printf=%U:%G ' . writetarget)) let modes=system('stat --printf=c%a ' . writetarget) exec '!sudo cp' shellescape(fname) writetarget exec '!sudo chmod' modes writetarget exec '!sudo chown' owner writetarget endfunction
Warning There is no check for symlinks. A symlink would be removed and replaced by a file with the symlink's modes, which are 777.
Suggestion 3[]
Here is a mapping to save to a /tmp
file, then overwrite the working file.
nnoremap <leader>es :w! /tmp/sudoSave \| let $fileToSave=expand('%') \| let $fileToSaveBackup=expand('%').'~' \| !sudo cp $fileToSave $fileToSaveBackup && sudo cp /tmp/sudoSave $fileToSave<CR><ESC>:e!<CR>
Warning This command will reload the file; you will lose the modifications history (undo will not work, although it does keep a backup).
Note that a backup is made, even when 'nobackup
' is set.
Comments[]
Use script#729 which has had more testing or use script#2709 which is an improved version of the first plugin (since it is not developed any more).