Ottenere i permessi di root su un file all'interno di vi? [chiuso]


245

Spesso durante la modifica dei file di configurazione, ne apro uno con vi e poi quando vado a salvarlo mi rendo conto che non ho digitato

sudo vi filename

C'è un modo per dare i privilegi di vi sudo per salvare il file? Mi sembra di ricordare di aver visto qualcosa al riguardo mentre cercavo alcune cose su vi qualche tempo fa, ma ora non riesco a trovarlo.


forse solo salvare una copia nella vostra home directory e "sudo mv" in un secondo momento
paan

Risposte:


296

% viene sostituito con il nome del file corrente, quindi è possibile utilizzare:

:w !sudo tee %

( vimrileverà che il file è stato modificato e chiederà se si desidera ricaricarlo. Di 'di sì scegliendo [L]invece di 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 migliore (secondo me) di farlo:

cmap w!! w !sudo tee >/dev/null %

In questo modo è possibile digitare :w!!e verrà espanso alla riga di comando completa, lasciando il cursore alla fine, quindi è possibile sostituire il %con un nome file, se lo si desidera.


5
Funziona con gvim? L'esecuzione del comando fa sì che Vim richieda la password ma non accetta l'input. Alla fine sudo: 1 incorrect password attempt
scade

non vedrei alcun motivo per cui gvim si comporti in modo diverso ... sei sicuro che sudo funzioni da solo?

Se hai bisogno dei privilegi di root per salvare un nuovo file, sostituisci% con il nome (incluso il percorso) del nuovo file.
gvkv

A volte, devi prima aggiungere il tuo utente al file sudoer, inserire l'utente root e aprire il /etc/sudoersfile, aggiungere your_username ALL=(ALL) ALLsotto la linea root ALL=(ALL) ALL, uscire e salvare.
cool il

1
@coolesting: 1) ci sono circa mille altre cose che devi fare ... non possiamo elencarle tutte. 2) dovresti sempre usare visudo.

32

In generale, non è possibile modificare l'ID utente effettivo del processo vi, ma è possibile farlo:

:w !sudo tee myfile

1
:w !sudo tee % >/dev/nullo :w !sudo dd of=%evitare di ripetere l'eco del contenuto del file mentre il file viene salvato.
Jamessan,

Puoi spiegare come funziona? Ho cercato teee visto che è un comando pipe Unix, e !inserisco un comando shell. La :wscrittura è fuori standard, che viene reindirizzata tee?
Eric Hu,

4
@Eric, esatto. il comando "tee myfile" copia lo stdin in myfile. l'esecuzione di "sudo tee myfile" farà lo stesso, ma poiché il processo tee è di proprietà di root, anche myfile sarà di proprietà di root. Sul lato vi, ": w! Some command line" reindirizzerà tutte le righe a "some command line".
Mark Harrison,

16

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 hanno 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, specialmente 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 dal comando. In questo caso, vogliamo interrompere il Press any key to continueprompt simile a quello che appare dopo aver eseguito il :!comando.

exec[ute]esegue una stringa come comando. Non possiamo semplicemente eseguire :writeperché non elaborerà la chiamata di funzione necessaria.

!rappresenta il :!comando: l'unico comando che :writeaccetta. Normalmente, :writeaccetta un percorso di file in cui scrivere. :!da solo esegue un comando in una shell (ad esempio, usando bash -c). Con :write, eseguirà il comando nella shell e quindi scriverà l'intero file stdin.

sudodovrebbe essere ovvio, poiché è per questo che sei qui. Esegui il comando come superutente. Ci sono molte informazioni in rete su come funziona.

teepipe stdinal file specificato. :writescriverà su stdin, quindi il superutente teericeverà il contenuto del file e scriverà il file. Non creerà un nuovo file - basta sovrascrivere il contenuto - quindi le modalità e gli attributi del file verranno preservati.

shellescape()sfugge ai caratteri speciali nel percorso del file indicato come appropriato per la shell corrente. Con un solo parametro, in genere racchiuderebbe il percorso tra virgolette, se necessario. Dato che stiamo inviando a una riga di comando della shell completa, vorremmo passare un valore diverso da zero come secondo argomento per consentire l'escape di backslash di altri caratteri speciali che potrebbero altrimenti inciampare nella 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 omesso il simbolo commerciale. A seconda della posizione, %è un'espressione valida e ha lo stesso effetto della lettura del %registro. Nidificato all'interno di un'altra espressione, in genere il collegamento non è consentito: come in questo caso.

>NULe >/dev/nullreindirizzare stdoutal dispositivo null della piattaforma. Anche se abbiamo messo a tacere il comando, non vogliamo che tutte le spese generali associate al piping stdintornino a VIM - è meglio scaricarlo il prima possibile. NULè il dispositivo null su DOS, MS-DOS e Windows, non è un file valido. A partire dal reindirizzamento di Windows 8 su NUL non risulta che un file chiamato NUL venga scritto. Prova a creare un file sul desktop chiamato NUL, con o senza estensione: non sarai in grado di farlo. (Ci sono molti altri nomi di dispositivi in ​​Windows che potrebbero valere la pena di conoscere.)

~ / .Vimrc

Platform-Dependent

Naturalmente, non vuoi ancora memorizzarli e digitarli ogni volta. È molto più facile associare il comando appropriato a un comando utente più semplice. Per fare ciò su POSIX, puoi aggiungere la seguente riga al tuo ~/.vimrcfile, creandolo se non esiste già:

command W silent execute 'write !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'

Ciò ti consentirà di digitare il comando: W (sensibile al maiuscolo / minuscolo) per scrivere il file corrente con autorizzazioni di superutente - molto più semplice.

Piattaforma indipendente

Uso un ~/.vimrcfile indipendente dalla piattaforma che si sincronizza tra i computer, quindi ho aggiunto la mia funzionalità multipiattaforma al mio. Ecco un ~/.vimrccon 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

Che cosa succede se si esegue il trip di Windows creando effettivamente un file scrivibile dal mondo in C: \ dev \ null?
Paul Stelian,

1
@PaulStelian Possibile, ma improbabile. È possibile estendere facilmente questo codice per tenere conto di una varietà di piattaforme e circostanze. In realtà, è improbabile che si verifichi una situazione su Windows dove sudoesiste ma non lo è /dev/null, quindi sarebbe necessario diventare più fantasiosi se si voleva un vero supporto multipiattaforma. È più un'introduzione: spunti di riflessione. :)
Zenexer,

11

Se stai usando Vim , è disponibile uno script chiamato sudo.vim . Se scopri di aver aperto un file di cui hai bisogno per accedere a 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 per la lettura e la scrittura.


4
Non consiglierei di usare questo script in quanto non prende le dovute precauzioni per sfuggire ai nomi dei file.
Jamessan,

7

Il consiglio di Ryan è generalmente buono, tuttavia, se dopo il passaggio 3, non spostare il file temporaneo; avrà la proprietà e le autorizzazioni sbagliate. Invece, sudoeditil file corretto e leggere il contenuto (usando :ro simili) del file temporaneo.

Se si segue il passaggio 2, utilizzare :w!per forzare la scrittura del file.


3

Quando si passa alla modalità di inserimento su un file, è necessario l'accesso sudo per la modifica, viene visualizzato un messaggio di stato

-- 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 circolare per farlo, ma funziona.


cat $ tmp> $ target è creativo, ma c'è qualche motivo per non annullare semplicemente il file?
ojrac,

Buon punto .. C'era anche un grosso problema con qualcosa sudo cat> / etc / blah - che userà sudo per cat il file, quindi l'utente normale per scrivere su / etc / blah (che non funzionerà) .. Risolto il problema in la risposta, e ha aggiunto la vostra dolce suggerimento sudo mv ..
DBR

Il suggerimento mv non conserva le autorizzazioni.
Paul Stelian,

1

Un rapido Google sembra dare questo consiglio:

  1. Non provare a modificare se è di sola lettura.
  2. Potrebbe essere possibile modificare le autorizzazioni sul file. (Se ti permetterà o meno di salvare dipende dalla sperimentazione.)
  3. Se hai comunque modificato comunque, salva in un file temporaneo e poi spostalo.

http://ubuntuforums.org/showthread.php?t=782136



0

Ho questo nel mio ~ / .bashrc:

alias svim='sudo vim'

Ora, ogni volta che devo modificare un file di configurazione, lo apro semplicemente con svim.


2
Il sudoeditcomando dovrebbe essere preferito poiché non richiede l'esecuzione di vim come root.
Jamessan,

2
Questo comunque non ti impedisce di legare vim invece di svim che è ciò a cui l'OP ha eluso.
ScaryAardvark,

3
-1, Questo sta solo dicendo "ricordati di digitare sudo quando apri un file", l'OP vuole sapere come possono ottenere i privilegi di root all'interno di vi.
Brad Koch,

-2

Un trucco rapido che puoi prendere in considerazione è fare un chmod sul file che stai modificando, salvarlo con vim e quindi tornare a quello che era il file originariamente.

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)

Naturalmente non raccomando questo approccio in un sistema in cui sei preoccupato per la sicurezza, poiché per alcuni secondi chiunque può leggere / modificare il file senza che te ne accorga.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.