Mendapatkan izin root pada file di dalam vi? [Tutup]

245

Seringkali saat mengedit file konfigurasi, saya akan membukanya dengan vi dan kemudian ketika saya pergi untuk menyimpannya menyadari bahwa saya tidak mengetik

sudo vi filename

Apakah ada cara untuk memberikan hak akses vi sudo untuk menyimpan file? Sepertinya saya ingat pernah melihat sesuatu tentang ini ketika mencari beberapa hal tentang vi beberapa waktu yang lalu, tetapi sekarang saya tidak dapat menemukannya.

Paul Wicks
sumber
mungkin hanya menyimpan salinan di direktori home Anda dan "sudo mv" nanti
paan

Jawaban:

296

% diganti dengan nama file saat ini, sehingga Anda dapat menggunakan:

:w !sudo tee %

( vimakan mendeteksi bahwa file telah diubah dan bertanya apakah Anda ingin memuatnya kembali. Katakan ya dengan memilih [L]daripada OK.)

Sebagai jalan pintas, Anda dapat mendefinisikan perintah Anda sendiri. Masukkan yang berikut ini di .vimrc:

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

Dengan di atas Anda dapat mengetik :W<Enter>untuk menyimpan file. Sejak saya menulis ini, saya telah menemukan cara yang lebih baik (menurut saya) untuk melakukan ini:

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

Dengan cara ini Anda dapat mengetik :w!!dan itu akan diperluas ke baris perintah penuh, meninggalkan kursor di akhir, sehingga Anda dapat mengganti %dengan nama file Anda sendiri, jika Anda mau.

beroe
sumber
5
Apakah ini berfungsi di gvim? Menjalankan perintah menyebabkan Vim meminta kata sandi tetapi tidak menerima input. Akhirnya waktu dua kali keluar dan mengatakan:sudo: 1 incorrect password attempt
cmcginty
saya tidak akan melihat alasan bagi gvim untuk berperilaku berbeda ... apakah Anda yakin sudo bekerja dengan benar?
Jika Anda membutuhkan hak akses root untuk menyimpan file baru, ganti% dengan nama (termasuk jalur) file baru.
gvkv
Kadang-kadang, Anda perlu menambahkan pengguna Anda ke file sudoer terlebih dahulu, masukkan pengguna root, dan buka /etc/sudoersfile, tambahkan di your_username ALL=(ALL) ALLbawah garis root ALL=(ALL) ALL, berhenti dan simpan.
keren
1
@coolesting: 1) ada sekitar seribu hal lain yang perlu Anda lakukan ... kami tidak bisa mendaftar semuanya. 2) Anda harus selalu menggunakan visudo.
32

Secara umum, Anda tidak dapat mengubah id pengguna yang efektif dari proses vi, tetapi Anda dapat melakukan ini:

:w !sudo tee myfile
Mark Harrison
sumber
1
:w !sudo tee % >/dev/nullatau :w !sudo dd of=%menghindari konten file digemakan kembali saat file disimpan.
jamessan
Bisakah Anda menjelaskan cara kerjanya? Saya melihat ke atas teedan melihat itu adalah perintah pipa Unix, dan !memasukkan perintah shell. Apakah :wpenulisan dengan standar keluar, yang akan disalurkan tee?
Eric Hu
4
@ Eric, itu benar. perintah "tee myfile" akan menyalin stdin ke myfile. menjalankan "sudo tee myfile" akan melakukan hal yang sama, tetapi karena proses tee dimiliki oleh root, myfile juga akan dimiliki oleh root. Di sisi vi, ": w! Some command line" akan menyalurkan semua baris ke "some command line".
Mark Harrison
16

Peringatan umum

Metode yang paling umum untuk mengatasi masalah file read-only adalah membuka pipa ke file saat ini sebagai pengguna super menggunakan implementasi sudo tee. Namun, semua solusi paling populer yang saya temukan di Internet memiliki kombinasi beberapa peringatan potensial:

  • Seluruh file ditulis ke terminal, serta file. Ini bisa lambat untuk file besar, terutama melalui koneksi jaringan yang lambat.
  • File kehilangan mode dan atribut serupa.
  • Jalur file dengan karakter atau spasi yang tidak biasa mungkin tidak ditangani dengan benar.

Solusi

Untuk mengatasi semua masalah ini, Anda dapat menggunakan perintah berikut:

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

Ini dapat disingkat, dengan hormat:

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

Penjelasan

:memulai perintah; Anda harus mengetikkan karakter ini dalam mode normal untuk mulai memasukkan perintah. Itu harus dihilangkan dalam skrip.

sil[ent]menekan output dari perintah. Dalam hal ini, kami ingin menghentikan Press any key to continueprompt-like yang muncul setelah menjalankan :!perintah.

exec[ute]mengeksekusi string sebagai perintah. Kami tidak bisa hanya menjalankannya :writekarena itu tidak akan memproses pemanggilan fungsi yang diperlukan.

!mewakili :!perintah: satu-satunya perintah yang :writemenerima. Biasanya, :writemenerima jalur file yang akan ditulis. :!dengan sendirinya menjalankan perintah di shell (misalnya, menggunakan bash -c). Dengan :write, itu akan menjalankan perintah di shell, dan kemudian menulis seluruh file stdin.

sudoharus jelas, karena itu kau ada di sini. Jalankan perintah sebagai pengguna super. Ada banyak informasi di internet tentang cara kerjanya.

teepipa stdinke file yang diberikan. :writeakan menulis ke stdin, maka pengguna super teeakan menerima konten file dan menulis file. Itu tidak akan membuat file baru - cukup timpa isinya - sehingga mode dan atribut file akan dipertahankan.

shellescape()lolos karakter khusus di jalur file yang diberikan sesuai untuk shell saat ini. Dengan hanya satu parameter, biasanya hanya menyertakan path dalam tanda kutip yang diperlukan. Karena kami mengirim ke baris perintah shell penuh, kami ingin memberikan nilai bukan nol sebagai argumen kedua untuk mengaktifkan backslash-escape dari karakter khusus lain yang mungkin menjebak shell.

@%membaca isi %register, yang berisi nama file buffer saat ini. Itu belum tentu jalur absolut, jadi pastikan Anda belum mengubah direktori saat ini. Dalam beberapa solusi, Anda akan melihat simbol komersial saat dihilangkan. Bergantung pada lokasi, %adalah ekspresi yang valid, dan memiliki efek yang sama dengan membaca %register. Bersarang di dalam ungkapan lain pintasan umumnya tidak diizinkan: seperti dalam kasus ini.

>NULdan >/dev/nullredirect stdoutke perangkat nol platform. Meskipun kami telah membungkam perintah, kami tidak ingin semua overhead terkait dengan pemipaan stdinkembali ke vim - terbaik untuk membuangnya sedini mungkin. NULadalah perangkat nol pada DOS, MS-DOS, dan Windows, bukan file yang valid. Pada pengalihan Windows 8 ke NUL tidak menghasilkan file bernama NUL sedang ditulis. Coba buat file di desktop Anda bernama NUL, dengan atau tanpa ekstensi file: Anda tidak akan bisa melakukannya. (Ada beberapa nama perangkat lain di Windows yang mungkin perlu Anda ketahui.)

~ / .vimrc

Platform-Ketergantungan

Tentu saja, Anda masih tidak ingin mengingatnya dan mengetiknya setiap kali. Jauh lebih mudah untuk memetakan perintah yang sesuai ke perintah pengguna yang lebih sederhana. Untuk melakukan ini pada POSIX, Anda bisa menambahkan baris berikut ke ~/.vimrcfile Anda , membuatnya jika belum ada:

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

Ini akan memungkinkan Anda untuk mengetik perintah: W (peka huruf besar kecil) untuk menulis file saat ini dengan izin pengguna super - jauh lebih mudah.

Platform-Independen

Saya menggunakan file platform-independen ~/.vimrcyang menyinkronkan di seluruh komputer, jadi saya menambahkan fungsionalitas multi-platform untuk menambang. Berikut ini ~/.vimrcdengan hanya pengaturan yang relevan:

#!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
sumber
Bagaimana jika Anda tersandung Windows dengan benar-benar membuat file yang dapat ditulis dunia di C: \ dev \ null?
Paul Stelian
1
@PaulStelian Kemungkinan, tetapi tidak mungkin. Anda dapat dengan mudah memperluas kode ini ke akun untuk berbagai platform dan keadaan. Pada kenyataannya, Anda tidak mungkin menghadapi situasi di Windows di mana sudoada tetapi tidak /dev/null, jadi Anda harus menjadi pelamun jika Anda menginginkan dukungan lintas platform yang benar. Ini lebih merupakan pengantar - makanan untuk dipikirkan. :)
Zenexer
11

Jika Anda menggunakan Vim , ada skrip yang tersedia bernama sudo.vim . Jika Anda menemukan bahwa Anda telah membuka file yang Anda perlu akses root untuk membaca, ketikkan

: e sudo:%
Vim mengganti% dengan nama file saat ini, dan sudo:menginstruksikan skrip sudo.vim untuk mengambil alih membaca dan menulis.

singkat
sumber
4
Saya tidak akan merekomendasikan menggunakan skrip ini karena tidak mengambil tindakan pencegahan yang tepat dengan melarikan diri nama file.
jamessan
7

Saran Ryan umumnya baik, namun, jika mengikuti langkah 3, jangan pindahkan file sementara; itu akan memiliki kepemilikan dan izin yang salah. Sebaliknya, sudoeditfile yang benar dan baca dalam konten (menggunakan :ratau sejenisnya) dari file sementara.

Jika mengikuti langkah 2, gunakan :w!untuk memaksa file untuk ditulis.

Chris Jester-Young
sumber
3

Ketika Anda masuk ke mode penyisipan pada file yang Anda butuhkan akses sudo untuk mengedit, Anda mendapatkan pesan status mengatakan

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

Jika saya melewatkan itu, umumnya saya lakukan

:w ~/edited_blah.tmp
:q

..kemudian..

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

..atau..

sudo mv edited_blah.tmp /etc/blah

Mungkin ada cara yang tidak terlalu bundar untuk melakukannya, tetapi berhasil.

dbr
sumber
cat $ tmp> $ target kreatif, tetapi apakah ada alasan untuk tidak hanya sudo mv file?
ojrac
Poin bagus .. Ada juga masalah besar dengan sudo cat sesuatu> / etc / bla - yang akan menggunakan sudo untuk menyimpan file, kemudian pengguna biasa menulis ke / etc / bla (yang tidak akan berfungsi) .. Memperbaiki di jawabannya, dan menambahkan saran sudo mv yang lebih baik ..
dbr
Saran mv tidak mempertahankan izin.
Paul Stelian
1

Google cepat sepertinya memberikan saran ini:

  1. Jangan mencoba mengedit jika hanya baca.
  2. Anda mungkin dapat mengubah izin pada file. (Apakah itu akan membiarkan Anda menyimpan atau tidak, masih dalam eksperimen.)
  3. Jika Anda masih diedit, simpan ke file sementara dan kemudian pindahkan.

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

Ryan Fox
sumber
1

Ini satu lagi yang telah muncul sejak pertanyaan ini dijawab, sebuah plugin bernama SudoEdit yang menyediakan fungsi SudoRead dan SudoWrite, yang secara default akan mencoba menggunakan sudo terlebih dahulu dan su jika gagal: http://www.vim.org/scripts/ script.php? script_id = 2709

James Snyder
sumber
0

Saya memiliki ini di ~ / .bashrc saya:

alias svim='sudo vim'

Sekarang setiap kali saya perlu mengedit file konfigurasi saya hanya membukanya dengan svim.

pisswillis
sumber
2
The sudoeditperintah harus disukai karena tidak memerlukan menjalankan vim sebagai root.
jamessan
2
Ini masih tidak menghentikan Anda mengikat vim daripada svim yang merupakan tujuan OP.
ScaryAardvark
3
-1, Ini hanya mengatakan "ingatlah untuk mengetikkan sudo ketika membuka file", OP ingin tahu bagaimana mereka bisa mendapatkan hak akses root di dalam vi.
Brad Koch
-2

Retas cepat yang dapat Anda pertimbangkan adalah melakukan chmod pada file yang Anda edit, simpan dengan vim, dan kemudian chmod kembali ke file aslinya.

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)

Tentu saja saya tidak merekomendasikan pendekatan ini dalam sistem di mana Anda khawatir tentang keamanan, karena selama beberapa detik siapa pun dapat membaca / mengubah file tanpa Anda sadari.

num1
sumber