Obtenir les autorisations root sur un fichier à l'intérieur de vi? [fermé]

245

Souvent, lors de l'édition des fichiers de configuration, j'en ouvrirai un avec vi, puis lorsque je l'enregistrerai, je me rendrai compte que je n'ai pas tapé

sudo vi filename

Existe-t-il un moyen de donner des privilèges à vi sudo pour enregistrer le fichier? Je semble me rappeler avoir vu quelque chose à ce sujet tout en recherchant des informations sur vi il y a quelque temps, mais maintenant je ne peux pas le trouver.

Paul Wicks
la source
peut-être simplement enregistrer une copie dans votre répertoire personnel et "sudo mv" plus tard
paan

Réponses:

296

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

:w !sudo tee %

( vimdé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 tant que 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 meilleure façon (à mon avis) de le faire:

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, en laissant le curseur à la fin, afin que vous puissiez remplacer le %par un nom de fichier de votre choix, si vous le souhaitez.

Beroe
la source
5
Est-ce que cela fonctionne dans gvim? L'exécution de la commande fait que Vim demande un mot de passe mais n'accepte pas l'entrée. Il sudo: 1 incorrect password attempt
arrive finalement à expiration
je ne verrais aucune raison pour que gvim se comporte différemment ... êtes-vous sûr que sudo en lui-même fonctionne correctement?
Si vous avez besoin des privilèges root pour enregistrer un nouveau fichier, remplacez% par le nom (y compris le chemin) du nouveau fichier.
gvkv
Parfois, vous devez d'abord ajouter votre utilisateur au fichier sudoer, saisir l'utilisateur root et ouvrir le /etc/sudoersfichier, ajouter your_username ALL=(ALL) ALLsous la ligne root ALL=(ALL) ALL, quitter et enregistrer.
coolesting
1
@coolesting: 1) il y a environ mille autres choses que vous devez faire… nous ne pouvons pas toutes les énumérer. 2) vous devez toujours utiliser visudo.
32

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
Mark Harrison
la source
1
:w !sudo tee % >/dev/nullou :w !sudo dd of=%évitez d'avoir le contenu du fichier renvoyé en écho lors de l'enregistrement du fichier.
jamessan
Pouvez-vous expliquer comment cela fonctionne? J'ai levé les yeux teeet je vois que c'est une commande de canal Unix et !insère une commande shell. L' :wécriture est-elle standard, qui est acheminée tee?
Eric Hu
4
@Eric, c'est vrai. la commande "tee myfile" copiera stdin dans myfile. exécuter "sudo tee myfile" fera de même, mais comme le processus de tee appartient à root, myfile appartiendra également à root. Côté vi, ": w! Une ligne de commande" dirigera toutes les lignes vers "une ligne de commande".
Mark Harrison
16

Avertissements courants

La méthode la plus courante pour contourner le problème des fichiers 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 ont une combinaison de 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 avec des caractères ou des espaces inhabituels peuvent ne pas être géré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 à entrer une commande. Il doit être omis dans les scripts.

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

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

!représente la :!commande: la seule commande qui :writeaccepte. Normalement, :writeaccepte un chemin de fichier dans lequel écrire. :!seule 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 le fichier entier dans stdin.

sudodevrait être évident, car c'est pourquoi vous êtes ici. Exécutez la commande en tant que super-utilisateur. Il y a beaucoup d'informations sur le net sur la façon dont cela fonctionne.

teetuyaux stdinvers le fichier donné. :writeva écrire dans stdin, puis le super-utilisateur teerecevra le contenu du fichier et écrit le fichier. Il ne créera pas de nouveau fichier - juste écraser le contenu - ainsi les modes et attributs de fichier seront préservés.

shellescape()échappe les caractères spéciaux dans le chemin d'accès au fichier donné, comme approprié pour le 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 complète du shell, nous souhaitons passer une valeur non nulle comme deuxième argument pour permettre l'échappement de 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, assurez-vous donc que vous n'avez pas changé le répertoire courant. Dans certaines solutions, le symbole commercial-at sera omis. Selon l'emplacement, %est une expression valide et a le même effet que la lecture du %registre. Cependant, imbriqué dans une autre expression, le raccourci est généralement interdit: comme dans ce cas.

>NULet >/dev/nullredirigez stdoutvers le périphérique nul de la plate-forme. Même si nous avons réduit la commande au silence, nous ne voulons pas que tous les frais généraux associés à la tuyauterie soient stdinrenvoyés à vim - le mieux est de la vider le plus tôt possible. NULest le périphérique nul sous DOS, MS-DOS et Windows, pas 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 être utiles.)

~ / .vimrc

Dépendant de la plateforme

Bien sûr, vous ne voulez toujours pas les mémoriser et les taper à chaque fois. Il est beaucoup plus facile de mapper la commande appropriée à une commande utilisateur plus simple. Pour ce faire sur POSIX, vous pouvez ajouter la ligne suivante à votre ~/.vimrcfichier, en la créant si elle 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 des autorisations de super-utilisateur - beaucoup plus facile.

Indépendant de la plateforme

J'utilise un ~/.vimrcfichier indépendant de la plate-forme qui se synchronise entre les ordinateurs, j'ai donc ajouté une fonctionnalité multi-plate-forme au mien. Voici un ~/.vimrcavec 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
Zenexer
la source
Que faire si vous déclenchez Windows en créant réellement un fichier accessible en écriture dans C: \ dev \ null?
Paul Stelian
1
@PaulStelian Possible, mais peu probable. Vous pouvez facilement étendre ce code pour tenir compte de diverses plates-formes et circonstances. En réalité, il est peu probable que vous rencontriez une situation sur Windows où elle sudoexiste, mais pas /dev/null, vous devez donc devenir plus sophistiqué si vous souhaitez une véritable prise en charge multiplateforme. C'est plus une introduction - matière à réflexion. :)
Zenexer
11

Si vous utilisez Vim , un script disponible est nommé sudo.vim . Si vous trouvez que vous avez ouvert un fichier dont vous avez besoin d'un accès root pour 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.

éphémère
la source
4
Je ne recommanderais pas d'utiliser ce script car il ne prend pas les précautions appropriées avec les noms de fichiers d'échappement.
jamessan
7

Les conseils de Ryan sont généralement bons, cependant, si après l'étape 3, ne déplacez pas le fichier temporaire; il aura la mauvaise propriété et les mauvaises autorisations. Au lieu de cela, sudoeditle fichier correct et lire le contenu (en utilisant :rou similaire) du fichier temporaire.

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

Chris Jester-Young
la source
3

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

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

Si ça me manque, en général je le fais

:w ~/edited_blah.tmp
:q

..puis..

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

..ou..

sudo mv edited_blah.tmp /etc/blah

Il y a probablement une façon moins détournée de le faire, mais cela fonctionne.

dbr
la source
cat $ tmp> $ target est créatif, mais y a-t-il une raison pour ne pas simplement sudo mv le fichier?
ojrac
Bon point .. Il y avait aussi un gros problème avec sudo cat quelque chose> / etc / blah - qui utilisera sudo pour cat le fichier, puis l'utilisateur normal pour écrire dans / etc / blah (qui ne fonctionnera pas) .. Corrigé dans la réponse, et ajouté votre meilleure suggestion sudo mv ..
dbr
La suggestion mv ne conserve pas les autorisations.
Paul Stelian
1

Un rapide Google semble donner ce conseil:

  1. N'essayez pas de le 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é de toute façon, enregistrez-le dans un fichier temporaire puis déplacez-le.

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

Ryan Fox
la source
1

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

James Snyder
la source
0

J'ai ceci dans mon ~ / .bashrc:

alias svim='sudo vim'

Maintenant, chaque fois que j'ai besoin de modifier un fichier de configuration, je l'ouvre avec svim.

pisswillis
la source
2
La sudoeditcommande doit être préférée car elle ne nécessite pas d'exécuter vim en tant que root.
jamessan
2
Cela ne vous empêche toujours pas de lier vim au lieu de svim, ce à quoi l'OP a échappé.
ScaryAardvark
3
-1, c'est juste dire "n'oubliez pas de taper sudo lors de l'ouverture d'un fichier", l'OP veut savoir comment ils peuvent obtenir les privilèges root à l'intérieur de vi.
Brad Koch
-2

Un hack rapide que vous pouvez envisager consiste à faire un chmod sur le fichier que vous modifiez, à enregistrer avec vim, puis à revenir à ce que le fichier était à l'origine.

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.

num1
la source