linux - salir - vi ir al final del archivo




¿Obteniendo permisos de root en un archivo dentro de vi? (7)

A menudo, al editar 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? Me parece recordar haber visto algo sobre esto mientras buscaba algo sobre vi hace un tiempo, pero ahora no puedo encontrarlo.


Advertencias comunes

El método más común para solucionar el problema de los archivos de solo lectura es abrir una tubería al archivo actual como superusuario mediante 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 posibles advertencias:

  • El archivo completo se escribe en el terminal, así como el archivo. Esto puede ser 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 usar 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 pueden ser acortados, respetuosamente:

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

Explicación

: comienza el comando; Necesitará escribir este carácter en modo normal para comenzar a ingresar un comando. Se debe omitir en los scripts.

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

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

! representa el :! comando: el único comando que :write acepta. Normalmente,: :write acepta una ruta de archivo para 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 a stdin .

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

tee tuberías stdin al archivo dado. :write se escribirá a stdin , luego el tee superusuario recibirá el contenido del archivo y lo escribirá. No creará un nuevo archivo, solo sobrescribirá el contenido, por lo que los modos y atributos de los archivos se conservarán.

shellescape() escapa caracteres especiales en la ruta del archivo dado según sea apropiado para el shell actual. Con un solo parámetro, por lo general, solo incluiría la ruta entre comillas según sea necesario. Ya que estamos enviando a una línea de comando de shell completa, desearemos pasar un valor distinto de cero como segundo argumento para habilitar la barra invertida y otros caracteres especiales que de otro modo podrían disparar la 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á el símbolo comercial en omitido. Dependiendo de la ubicación, % es una expresión válida, y tiene el mismo efecto que leer el registro % . Sin embargo, anidado dentro de otra expresión, el acceso directo generalmente no está permitido: como en este caso.

>NUL y >/dev/null redireccionan la stdout al dispositivo nulo de la plataforma. A pesar de que hemos silenciado el comando, no queremos que toda la sobrecarga asociada con la tubería stdin vuelva a configurar en Vim, lo mejor es volcarlo 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 lugar a que se escriba un archivo llamado NUL. Intente crear un archivo en su escritorio llamado NUL, con o sin una extensión de archivo: no podrá hacerlo. (Hay otros nombres de dispositivos en Windows que vale la pena conocer).

~ / .vimrc

Dependiente de la plataforma

Por supuesto, aún no desea 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 archivo ~/.vimrc , y crearla 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

Utilizo un archivo ~/.vimrc independiente de la plataforma que se sincroniza en todas las computadoras, por lo que agregué funcionalidad multiplataforma a la mía. Aquí hay un ~/.vimrc con solo las configuraciones relevantes:

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

Aquí hay otro que ha aparecido desde que se respondió esta pregunta, un complemento llamado SudoEdit que proporciona las funciones de SudoRead y SudoWrite, que intentará usar sudo en primer lugar y su si esto falla: http://www.vim.org/scripts/script.php?script_id=2709


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 equivocados. En su lugar, sudoedit el archivo correcto y lea el contenido (usando :r o similar) del archivo temporal.

Si sigue el paso 2, use :w! Para forzar el archivo a ser escrito.


En general, no puede cambiar el ID de usuario efectivo del proceso vi, pero puede hacer esto:

:w !sudo tee myfile

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 rápido Google parece dar este consejo:

  1. No intente editar si es de solo lectura.
  2. Es posible que pueda cambiar los permisos en el archivo. (Ya sea que te permita guardar o no, depende de la experimentación).
  3. Si todavía editó de todos modos, guárdelo en un archivo temporal y luego muévalo.

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


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

:w !sudo tee %

( vim detectará que el archivo ha sido cambiado y le preguntará si desea volver a cargarlo. Diga sí al seleccionar [L] lugar de OK.)

Como acceso directo, puede definir su propio comando. Ponga lo siguiente en su .vimrc :

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

Con lo anterior puede escribir :W<Enter> para guardar el archivo. Desde que escribí esto, he encontrado 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 comandos completa, dejando el cursor al final, para que pueda reemplazar el % con un nombre de archivo propio, si lo desea.





vi