Ottenere i permessi di root su un file all'interno di vi?
Domanda
Spesso mentre modifico i file di configurazione, ne apro uno con vi e poi quando vado a salvarlo mi accorgo che non ho digitato
sudo vi filename
Esiste un modo per concedere i privilegi di vi sudo per salvare il file?Mi sembra di ricordare di aver visto qualcosa a riguardo mentre cercavo alcune cose su vi qualche tempo fa, ma ora non riesco a trovarlo.
Soluzione
%
viene sostituito con il nome del file corrente, quindi puoi utilizzare:
:w !sudo tee %
(vim
rileverà che il file è stato modificato e ti chiederà se desideri che venga ricaricato.Di' sì scegliendo [L]
piuttosto che OK.)
Come scorciatoia, puoi definire il tuo comando.Inserisci quanto segue nel tuo .vimrc
:
command W w !sudo tee % >/dev/null
Con quanto sopra puoi digitare :W<Enter>
per salvare il file.Da quando ho scritto questo, ho trovato un modo più carino (secondo me) per farlo:
cmap w!! w !sudo tee >/dev/null %
In questo modo puoi digitare :w!!
e verrà espanso per l'intera riga di comando, lasciando il cursore alla fine, in modo da poter sostituire il file %
con un nome file personalizzato, se lo desideri.
Altri suggerimenti
In generale, non puoi modificare l'ID utente effettivo del processo vi, ma puoi farlo:
:w !sudo tee myfile
Avvertenze comuni
Il metodo più comune per aggirare il problema del file di sola lettura è aprire una pipe al file corrente come superutente utilizzando un'implementazione di sudo tee
.Tuttavia, tutte le soluzioni più popolari che ho trovato su Internet presentano una combinazione di diversi potenziali avvertimenti:
- L'intero file viene scritto sul terminale, così come il file.Questo può essere lento per file di grandi dimensioni, soprattutto su connessioni di rete lente.
- Il file perde le sue modalità e attributi simili.
- I percorsi dei file con caratteri o spazi insoliti potrebbero non essere gestiti correttamente.
Soluzioni
Per aggirare tutti questi problemi, è possibile utilizzare il seguente comando:
" 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'
Questi possono essere abbreviati, rispettosamente:
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL'
Spiegazione
:
inizia il comando;dovrai digitare questo carattere in modalità normale per iniziare a inserire un comando.Dovrebbe essere omesso negli script.
sil[ent]
sopprime l'output del comando.In questo caso, vogliamo interrompere il Press any key to continue
-like che appare dopo aver eseguito il file :!
comando.
exec[ute]
esegue una stringa come comando.Non possiamo semplicemente scappare :write
perché non elaborerà la chiamata di funzione necessaria.
!
rappresenta il :!
comando:l'unico comando che :write
accetta.Normalmente, :write
accetta un percorso di file su cui scrivere. :!
da solo esegue un comando in una shell (ad esempio, using bash -c
).Con :write
, eseguirà il comando nella shell e quindi scriverà l'intero file stdin
.
sudo
dovrebbe essere ovvio, visto che è per questo che sei qui.Esegui il comando come superutente.Ci sono moltissime informazioni in rete su come funziona.
tee
tubi stdin
al file specificato. :write
scriverò a stdin
, quindi il superutente tee
riceverà il contenuto del file e scriverà il file.Non creerà un nuovo file, ne sovrascriverà semplicemente il contenuto, quindi le modalità e gli attributi del file verranno preservati.
shellescape()
esegue l'escape dei caratteri speciali nel percorso del file specificato in modo appropriato per la shell corrente.Con un solo parametro, in genere racchiude semplicemente il percorso tra virgolette, se necessario.Poiché stiamo inviando a una riga di comando della shell completa, vorremo passare un valore diverso da zero come secondo argomento per abilitare l'escape con barra rovesciata di altri caratteri speciali che potrebbero altrimenti far inciampare la shell.
@%
legge il contenuto del %
registro, che contiene il nome del file del buffer corrente.Non è necessariamente un percorso assoluto, quindi assicurati di non aver modificato la directory corrente.In alcune soluzioni, vedrai il simbolo commerciale omesso.A seconda della posizione, %
è un'espressione valida e ha lo stesso effetto della lettura del file %
Registrati.Nidificata all'interno di un'altra espressione, la scorciatoia generalmente non è consentita, tuttavia:come in questo caso.
>NUL
E >/dev/null
reindirizzare stdout
al dispositivo nullo della piattaforma.Anche se abbiamo silenziato il comando, non vogliamo tutto il sovraccarico associato alle tubazioni stdin
torniamo a Vim: è meglio scaricarlo il prima possibile. NUL
è il dispositivo nullo su DOS, MS-DOS e Windows, non un file valido.A partire da Windows 8 i reindirizzamenti a NUL non comportano la scrittura di un file denominato NUL.Prova a creare un file sul desktop denominato NUL, con o senza estensione di file:non sarai in grado di farlo.(Ci sono molti altri nomi di dispositivi in Windows che potrebbe valere la pena conoscere.)
~/.vimrc
Dipendente dalla piattaforma
Naturalmente, non vuoi ancora memorizzarli e digitarli ogni volta.È molto più semplice associare il comando appropriato a un comando utente più semplice.Per fare ciò su POSIX, potresti aggiungere la seguente riga al tuo ~/.vimrc
file, creandolo se non esiste già:
command W silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
Ciò ti consentirà di digitare il comando :W (con distinzione tra maiuscole e minuscole) per scrivere il file corrente con autorizzazioni da superutente: molto più semplice.
Piattaforma indipendente
Io uso un indipendente dalla piattaforma ~/.vimrc
file che si sincronizza su più computer, quindi ho aggiunto la funzionalità multipiattaforma al mio.Ecco un ~/.vimrc
con solo le impostazioni pertinenti:
#!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
Se stai usando Vim, è disponibile uno script denominato sudo.vim.Se scopri di aver aperto un file per cui hai bisogno dell'accesso root per leggere, digita
:e sudo:%Vim sostituisce % con il nome del file corrente e
sudo:
indica allo script sudo.vim di assumere il controllo della lettura e della scrittura.
Il consiglio di Ryan è generalmente buono, tuttavia, se si segue il passaggio 3, non spostare il file temporaneo;avrà proprietà e autorizzazioni errate.Invece, sudoedit
il file corretto e leggerne il contenuto (utilizzando :r
o simili) del file temporaneo.
Se si segue il passaggio 2, utilizzare :w!
per forzare la scrittura del file.
Quando entri in modalità di inserimento su un file di cui hai bisogno sudo access per modificarlo, ricevi un messaggio di stato che dice
-- INSERT -- W10: Warning: Changing a readonly file
Se mi manca, generalmente lo faccio
:w ~/edited_blah.tmp
:q
..Poi..
sudo "cat edited_blah.tmp > /etc/blah"
..O..
sudo mv edited_blah.tmp /etc/blah
Probabilmente c'è un modo meno indiretto per farlo, ma funziona.
Un rapido Google sembra dare questo consiglio:
- Non provare a modificare se è di sola lettura.
- Potresti essere in grado di modificare le autorizzazioni sul file.(Se ti consentirà o meno di salvare dipende dalla sperimentazione.)
- Se hai comunque apportato modifiche, salva in un file temporaneo e quindi spostalo.
Eccone un altro che è apparso da quando è stata data risposta a questa domanda, un plugin chiamato SudoEdit che fornisce le funzioni SudoRead e SudoWrite, che per impostazione predefinita proveranno a utilizzare prima sudo e su se falliscono: http://www.vim.org/scripts/script.php?script_id=2709
Ho questo nel mio ~/.bashrc:
alias svim='sudo vim'
Ora ogni volta che devo modificare un file di configurazione, lo apro semplicemente con svim.
Un trucco veloce che puoi prendere in considerazione è eseguire un chmod sul file che stai modificando, salvarlo con vim e quindi tornare a ciò che era originariamente il file.
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)
Ovviamente non consiglio questo approccio in un sistema in cui sei preoccupato per la sicurezza, poiché per pochi secondi chiunque può leggere/modificare il file senza che tu te ne accorga.
utilizzo gksudo invece di sudo per GVim, ad es.
cmap w!! w !gksudo tee >/dev/null %