Pregunta

A menudo, mientras edito archivos de configuración, abro uno con vi y luego, cuando voy a guardarlo, me doy cuenta de que no escribí

sudo vi filename

¿Hay alguna forma de otorgar privilegios a vi sudo para guardar el archivo?Creo recordar haber visto algo sobre esto mientras buscaba algunas cosas sobre vi hace un tiempo, pero ahora no puedo encontrarlo.

¿Fue útil?

Solución

% se reemplaza con el nombre del archivo actual, por lo que puede usar:

:w !sudo tee %

(vim detectará que el archivo ha sido modificado y le preguntará si desea volver a cargarlo.Di que sí eligiendo [L] en lugar de estar bien.)

Como atajo, puedes definir tu propio comando.Pon lo siguiente en tu .vimrc:

command W w !sudo tee % >/dev/null

Con lo anterior puedes escribir :W<Enter> para guardar el archivo.Desde que escribí esto, encontré una manera mejor (en mi opinión) de hacer esto:

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

De esta manera puedes escribir :w!! y se expandirá a la línea de comando completa, dejando el cursor al final, para que pueda reemplazar el % con un nombre de archivo propio, si lo desea.

Otros consejos

En general, no puedes cambiar la identificación de usuario efectiva del proceso vi, pero puedes hacer esto:

:w !sudo tee myfile

Advertencias comunes

El método más común para solucionar el problema del archivo de solo lectura es abrir una tubería al archivo actual como superusuario utilizando una implementación de sudo tee.Sin embargo, todas las soluciones más populares que he encontrado en Internet tienen una combinación de varias advertencias potenciales:

  • Todo el archivo se escribe en la terminal, así como el archivo.Esto puede resultar lento para archivos grandes, especialmente en conexiones de red lentas.
  • El archivo pierde sus modos y atributos similares.
  • Es posible que las rutas de archivos con caracteres o espacios inusuales no se manejen correctamente.

Soluciones

Para solucionar todos estos problemas, puede utilizar el siguiente 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'

Estos se pueden acortar, respetuosamente:

:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >/dev/null'
:sil exec 'w !sudo tee ' . shellescape(@%, 1) . ' >NUL'

Explicación

: comienza el comando;deberá escribir este carácter en modo normal para comenzar a ingresar un comando.Debe omitirse en los guiones.

sil[ent] suprime la salida del comando.En este caso queremos detener el Press any key to continue-como mensaje que aparece después de ejecutar el :! dominio.

exec[ute] ejecuta una cadena como un comando.No podemos simplemente correr :write porque no procesará la llamada a la función necesaria.

! representa el :! dominio:el único comando que :write acepta.Normalmente, :write acepta una ruta de archivo en la que escribir. :! por sí solo ejecuta un comando en un shell (por ejemplo, usando bash -c).Con :write, ejecutará el comando en el shell y luego escribirá el archivo completo en stdin.

sudo Debería ser obvio, ya que es por eso que estás aquí.Ejecute el comando como superusuario.Hay mucha información en la red sobre cómo funciona.

tee tubería stdin al archivo dado. :write escribirá a stdin, entonces el superusuario tee Recibirá el contenido del archivo y escribirá el archivo.No creará un archivo nuevo, simplemente sobrescribirá el contenido, por lo que se conservarán los modos y atributos del archivo.

shellescape() escapa de los caracteres especiales en la ruta del archivo dada según corresponda para el shell actual.Con solo un parámetro, normalmente incluiría la ruta entre comillas según sea necesario.Dado que estamos enviando a una línea de comando de shell completa, queremos pasar un valor distinto de cero como segundo argumento para permitir el escape de barra invertida de otros caracteres especiales que, de otro modo, podrían alterar el shell.

@% lee el contenido del % registro, que contiene el nombre del archivo del búfer actual.No es necesariamente una ruta absoluta, así que asegúrese de no haber cambiado el directorio actual.En algunas soluciones, verá omitido el símbolo comercial arroba.Dependiendo de la ubicación, % es una expresión válida y tiene el mismo efecto que leer el % registro.Sin embargo, el atajo, anidado dentro de otra expresión, generalmente no está permitido:como en este caso.

>NUL y >/dev/null redirigir stdout al dispositivo nulo de la plataforma.Aunque hayamos silenciado el comando, no queremos que toda la sobrecarga asociada con las tuberías stdin Vuelva a vim; es mejor deshacerse de él lo antes posible. NUL es el dispositivo nulo en DOS, MS-DOS y Windows, no un archivo válido.A partir de Windows 8, las redirecciones a NUL no dan como resultado que se escriba un archivo llamado NUL.Intente crear un archivo en su escritorio llamado NUL, con o sin extensión de archivo:no podrás hacerlo.(Hay varios otros nombres de dispositivos en Windows que valdría la pena conocer).

~/.vimrc

Dependiente de la plataforma

Por supuesto, todavía no querrás memorizarlos y escribirlos cada vez.Es mucho más fácil asignar el comando apropiado a un comando de usuario más simple.Para hacer esto en POSIX, puede agregar la siguiente línea a su ~/.vimrc archivo, creándolo si aún no existe:

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

Esto le permitirá escribir el comando :W (distingue entre mayúsculas y minúsculas) para escribir el archivo actual con permisos de superusuario, mucho más fácil.

Plataforma independiente

Yo uso una plataforma independiente ~/.vimrc archivo que se sincroniza entre computadoras, así que agregué funcionalidad multiplataforma al mío.Aquí está un ~/.vimrc con sólo la configuración relevante:

#!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

Si estas usando Empuje, hay un script disponible llamado sudo.vim.Si descubre que ha abierto un archivo que necesita acceso de root para leer, escriba

:e sudo:%
Vim reemplaza % con el nombre del archivo actual y sudo: indica al script sudo.vim que se haga cargo de la lectura y escritura.

El consejo de Ryan es generalmente bueno; sin embargo, si sigue el paso 3, no mueva el archivo temporal;tendrá la propiedad y los permisos incorrectos.En cambio, sudoedit el archivo correcto y lea el contenido (usando :r o similares) del archivo temporal.

Si sigue el paso 2, utilice :w! para forzar la escritura del archivo.

Cuando ingresa al modo de inserción en un archivo que necesita acceso sudo para editar, recibe un mensaje de estado que dice

-- INSERT -- W10: Warning: Changing a readonly file

Si me pierdo eso, generalmente lo hago.

:w ~/edited_blah.tmp
:q

..entonces..

sudo "cat edited_blah.tmp > /etc/blah"

..o..

sudo mv edited_blah.tmp /etc/blah

Probablemente haya una forma menos indirecta de hacerlo, pero funciona.

Un Google rápido parece dar este consejo:

  1. No intentes editar si es de solo lectura.
  2. Es posible que pueda cambiar los permisos del archivo.(Si le permitirá guardar o no, depende de la experimentación).
  3. Si aún así editaste, guárdalo en un archivo temporal y luego muévelo.

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

Aquí hay otro que apareció desde que se respondió esta pregunta, un complemento llamado SudoEdit que proporciona funciones SudoRead y SudoWrite, que de forma predeterminada intentará usar sudo primero y su si falla: http://www.vim.org/scripts/script.php?script_id=2709

Tengo esto en mi ~/.bashrc:

alias svim='sudo vim'

Ahora, cada vez que necesito editar un archivo de configuración, simplemente lo abro con svim.

Un truco rápido que puede considerar es hacer un chmod en el archivo que está editando, guardarlo con vim y luego volver a modificar el archivo que era originalmente.

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)

Por supuesto, no recomiendo este enfoque en un sistema en el que esté preocupado por la seguridad, ya que durante unos segundos cualquiera puede leer/cambiar el archivo sin que usted se dé cuenta.

usar gksudo en lugar de sudo para GVim es decir

cmap w!! w !gksudo tee >/dev/null %
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top