Question

Souvent, en éditant des fichiers de configuration, j'en ouvre un avec vi et puis quand je vais le sauvegarder, je me rends compte que je n'ai pas tapé

sudo vi filename

Existe-t-il un moyen d'accorder à vi sudo les privilèges pour enregistrer le fichier ?Il me semble avoir vu quelque chose à ce sujet en recherchant des informations sur vi il y a quelque temps, mais maintenant je ne le trouve pas.

Était-ce utile?

La solution

% est remplacé par le nom du fichier actuel, vous pouvez donc utiliser :

:w !sudo tee %

(vim détectera que le fichier a été modifié et vous demandera si vous souhaitez qu'il soit rechargé.Dites oui en choisissant [L] plutôt que OK.)

En guise de raccourci, vous pouvez définir votre propre commande.Mettez ce qui suit dans votre .vimrc:

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

Avec ce qui précède, vous pouvez taper :W<Enter> pour enregistrer le fichier.Depuis que j'ai écrit ceci, j'ai trouvé une manière plus agréable (à mon avis) de procéder :

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

De cette façon, vous pouvez taper :w!! et il sera étendu à la ligne de commande complète, laissant le curseur à la fin, afin que vous puissiez remplacer le % avec votre propre nom de fichier, si vous le souhaitez.

Autres conseils

En général, vous ne pouvez pas modifier l'ID utilisateur effectif du processus vi, mais vous pouvez le faire :

:w !sudo tee myfile

Mises en garde courantes

La méthode la plus courante pour contourner le problème du fichier en lecture seule consiste à ouvrir un canal vers le fichier actuel en tant que super-utilisateur à l'aide d'une implémentation de sudo tee.Cependant, toutes les solutions les plus populaires que j’ai trouvées sur Internet combinent plusieurs mises en garde potentielles :

  • Le fichier entier est écrit sur le terminal, ainsi que le fichier.Cela peut être lent pour les fichiers volumineux, en particulier sur les connexions réseau lentes.
  • Le fichier perd ses modes et attributs similaires.
  • Les chemins de fichiers contenant des caractères ou des espaces inhabituels peuvent ne pas être traités correctement.

Solutions

Pour contourner tous ces problèmes, vous pouvez utiliser la commande suivante :

" 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'

Ceux-ci peuvent être raccourcis, respectueusement :

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

Explication

: commence la commande ;vous devrez taper ce caractère en mode normal pour commencer à saisir une commande.Il doit être omis dans les scripts.

sil[ent] supprime la sortie de la commande.Dans ce cas, nous voulons arrêter le Press any key to continue-une invite semblable à celle qui apparaît après l'exécution de :! commande.

exec[ute] exécute une chaîne en tant que commande.Nous ne pouvons pas simplement courir :write car il ne traitera pas l'appel de fonction nécessaire.

! représente le :! commande:la seule commande qui :write accepte.Normalement, :write accepte un chemin de fichier dans lequel écrire. :! à lui seul, exécute une commande dans un shell (par exemple, en utilisant bash -c).Avec :write, il exécutera la commande dans le shell, puis écrira l'intégralité du fichier dans stdin.

sudo Cela devrait être évident, puisque c'est pour cela que vous êtes ici.Exécutez la commande en tant que super-utilisateur.Il existe de nombreuses informations sur le net sur la façon dont cela fonctionne.

tee tuyaux stdin au fichier donné. :write j'écrirai à stdin, alors le super-utilisateur tee recevra le contenu du fichier et écrira le fichier.Il ne créera pas de nouveau fichier - écrasera simplement le contenu - afin que les modes et attributs du fichier soient préservés.

shellescape() échappe les caractères spéciaux dans le chemin de fichier donné en fonction du shell actuel.Avec un seul paramètre, il suffit généralement de placer le chemin entre guillemets si nécessaire.Puisque nous envoyons vers une ligne de commande shell complète, nous voudrons transmettre une valeur non nulle comme deuxième argument pour permettre l'échappement par barre oblique inverse d'autres caractères spéciaux qui pourraient autrement déclencher le shell.

@% lit le contenu du % registre, qui contient le nom de fichier du tampon actuel.Ce n'est pas nécessairement un chemin absolu, alors assurez-vous de ne pas avoir modifié le répertoire actuel.Dans certaines solutions, le symbole commercial-at est omis.Selon l'emplacement, % est une expression valide et a le même effet que la lecture du % registre.Imbriqué dans une autre expression, le raccourci est généralement interdit, cependant :comme dans ce cas.

>NUL et >/dev/null réorienter stdout au périphérique nul de la plateforme.Même si nous avons désactivé la commande, nous ne voulons pas que toute la surcharge associée à la tuyauterie stdin revenons à vim - il est préférable de le vider le plus tôt possible. NUL est le périphérique nul sous DOS, MS-DOS et Windows, et non un fichier valide.Depuis Windows 8, les redirections vers NUL n'entraînent pas l'écriture d'un fichier nommé NUL.Essayez de créer un fichier sur votre bureau nommé NUL, avec ou sans extension de fichier :vous ne pourrez pas le faire.(Il existe plusieurs autres noms de périphériques dans Windows qui pourraient valoir la peine d'être connus.)

~/.vimrc

Dépend de la plateforme

Bien sûr, vous ne voulez toujours pas les mémoriser et les saisir à chaque fois.Il est beaucoup plus facile de mapper la commande appropriée à une commande utilisateur plus simple.Pour ce faire sous POSIX, vous pouvez ajouter la ligne suivante à votre ~/.vimrc fichier, en le créant s'il n'existe pas déjà :

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

Cela vous permettra de taper la commande :W (sensible à la casse) pour écrire le fichier actuel avec les autorisations de super-utilisateur - beaucoup plus facilement.

Indépendant de la plateforme

J'utilise un outil indépendant de la plateforme ~/.vimrc fichier qui se synchronise sur tous les ordinateurs, j'ai donc ajouté une fonctionnalité multiplateforme au mien.Voici un ~/.vimrc avec uniquement les paramètres pertinents :

#!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 vous utilisez Vigueur, il existe un script disponible nommé sudo.vim.Si vous constatez que vous avez ouvert un fichier pour lequel vous avez besoin d'un accès root pour le lire, tapez

:e sudo:%
Vim remplace le % par le nom du fichier actuel, et sudo: demande au script sudo.vim de prendre le relais pour la lecture et l'écriture.

Les conseils de Ryan sont généralement bons, cependant, si vous suivez l'étape 3, ne déplacez pas le fichier temporaire ;il aura la mauvaise propriété et les mauvaises autorisations.Plutôt, sudoedit le bon fichier et lisez-en le contenu (en utilisant :r ou similaire) du fichier temporaire.

Si vous suivez l'étape 2, utilisez :w! pour forcer l'écriture du fichier.

Lorsque vous passez en mode insertion sur un fichier pour lequel vous avez besoin d'un accès sudo pour le modifier, vous recevez un message d'état indiquant

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

Si ça me manque, c'est généralement le cas

:w ~/edited_blah.tmp
:q

..alors..

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

..ou..

sudo mv edited_blah.tmp /etc/blah

Il existe probablement une manière moins détournée de procéder, mais cela fonctionne.

Un rapide Google semble donner ce conseil :

  1. N'essayez pas de modifier s'il est en lecture seule.
  2. Vous pourrez peut-être modifier les autorisations sur le fichier.(Que cela vous permette ou non d'économiser dépend de l'expérimentation.)
  3. Si vous avez quand même modifié, enregistrez-le dans un fichier temporaire, puis déplacez-le.

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

En voici un autre qui est apparu depuis la réponse à cette question, un plugin appelé SudoEdit qui fournit les fonctions SudoRead et SudoWrite, qui tenteront par défaut d'utiliser sudo en premier et su si cela échoue : http://www.vim.org/scripts/script.php?script_id=2709

J'ai ceci dans mon ~/.bashrc :

alias svim='sudo vim'

Désormais, chaque fois que j'ai besoin de modifier un fichier de configuration, je l'ouvre simplement avec svim.

Un hack rapide que vous pouvez envisager consiste à effectuer un chmod sur le fichier que vous modifiez, à l'enregistrer avec vim, puis à revenir à l'état d'origine du fichier.

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)

Bien sûr, je ne recommande pas cette approche dans un système où vous vous inquiétez de la sécurité, car pendant quelques secondes, n'importe qui peut lire/modifier le fichier sans que vous vous en rendiez compte.

utiliser gksudo au lieu de sudo pour GVim, c'est-à-dire

cmap w!! w !gksudo tee >/dev/null %
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top