Banyak dari Anda mungkin telah melihat perintah yang memungkinkan Anda untuk menulis pada file yang memerlukan izin root, bahkan ketika Anda lupa untuk membuka vim dengan sudo:
:w !sudo tee %
Masalahnya adalah saya tidak mengerti apa yang sebenarnya terjadi di sini.
Saya sudah memikirkan ini:
w
untuk ini
*:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
Execute {cmd} with [range] lines as standard input
(note the space in front of the '!'). {cmd} is
executed like with ":!{cmd}", any '!' is replaced with
the previous command |:!|.
sehingga melewati semua baris sebagai input standar.
Bagian ini !sudo tee
memanggil tee
dengan hak administrator.
Agar semua masuk akal, %
harus menampilkan nama file (sebagai parameter untuk tee
), tetapi saya tidak dapat menemukan referensi tentang bantuan untuk perilaku ini.
tl; dr Bisakah seseorang membantu saya membedah perintah ini?
:w !sudo cat > %
bekerja juga, dan tidak mencemari output standar?sudo
diterapkan kecat
, tetapi tidak untuk>
, jadi itu tidak diperbolehkan. Anda dapat mencoba menjalankan seluruh perintah dalam sebuah subkulit sudo, seperti:w !sudo sh -c "cat % > yams.txt"
, tetapi itu tidak akan berhasil, karena dalam subkulit,%
adalah nihil; Anda akan mengosongkan isi file Anda.:w !sudo sh -c "cat >%"
benar-benar berfungsi dengan baiksudo tee %
karena Vim mengganti nama file%
sebelum ia sampai ke subkulit. Namun, tak satu pun dari mereka bekerja jika nama file memiliki spasi di dalamnya; Anda harus melakukan:w !sudo sh -c "cat >'%'"
atau:w !sudo tee "%"
memperbaikinya.Jawaban:
Dalam
:w !sudo tee %
...%
berarti "file saat ini"Seperti yang ditunjukkan eugene ,
%
memang berarti "nama file saat ini", yang diteruskan ketee
sehingga ia tahu file mana yang akan ditimpa.(Dalam perintah substitusi, ini sedikit berbeda; seperti yang
:help :%
ditunjukkan, ituequal to 1,$ (the entire file)
(terima kasih kepada @Orafu untuk menunjukkan bahwa ini tidak mengevaluasi ke nama file). Misalnya,:%s/foo/bar
berarti " dalam file saat ini , ganti kemunculanfoo
dengan denganbar
." Jika Anda menyorot beberapa teks sebelum mengetik:s
, Anda akan melihat bahwa garis yang disorot menggantikan%
sebagai rentang substitusi Anda.):w
tidak memperbarui file AndaSalah satu bagian yang membingungkan dari trik ini adalah Anda mungkin berpikir
:w
memodifikasi file Anda, tetapi sebenarnya tidak. Jika Anda membuka dan memodifikasifile1.txt
, lalu berlari:w file2.txt
, itu akan menjadi "save as";file1.txt
tidak akan diubah, tetapi konten buffer saat ini akan dikirim kefile2.txt
.Alih-alih
file2.txt
, Anda bisa mengganti perintah shell untuk menerima konten buffer . Contohnya,:w !cat
hanya akan menampilkan konten.Jika Vim tidak dijalankan dengan akses sudo, itu
:w
tidak dapat memodifikasi file yang dilindungi, tetapi jika ia meneruskan konten buffer ke shell, perintah di shell dapat dijalankan dengan sudo . Dalam hal ini, kami menggunakantee
.Memahami tee
Adapun
tee
, gambartee
perintah sebagai pipa berbentuk T dalam situasi bash piping yang normal: ia mengarahkan output ke file yang ditentukan dan juga mengirimkannya ke output standar , yang dapat ditangkap oleh perintah pipa berikutnya.Misalnya, dalam
ps -ax | tee processes.txt | grep 'foo'
, daftar proses akan ditulis ke file teks dan diteruskan kegrep
.(Diagram dibuat dengan Asciiflow .)
Lihat
tee
halaman manual untuk info lebih lanjut.Tee sebagai peretasan
Dalam situasi yang dijelaskan oleh pertanyaan Anda, menggunakan
tee
adalah peretasan karena kami mengabaikan setengah dari fungsinya .sudo tee
menulis ke file kami dan juga mengirim konten buffer ke output standar, tetapi kami mengabaikan output standar . Kita tidak perlu meneruskan apa pun ke perintah pipa lain dalam kasus ini; kami hanya menggunakantee
sebagai cara alternatif untuk menulis file dan sehingga kami dapat menyebutnya dengansudo
.Membuat trik ini mudah
Anda dapat menambahkan ini ke Anda
.vimrc
untuk membuat trik ini mudah digunakan: cukup ketik:w!!
.The
> /dev/null
Bagian eksplisit membuang output standar, karena, seperti yang saya katakan, kita tidak harus lulus apapun untuk perintah pipa lain.sumber
tee
karena kemampuannya untuk menulis stdin ke file. Saya terkejut tidak ada program yang tugasnya melakukan itu (saya menemukan program yang belum pernah saya dengarsponge
yang melakukan ini). Saya kira khas "tulis aliran ke file" dilakukan oleh shell built-in. Apakah Vim!{cmd}
tidak membayar cangkang (cmd
sebagai gantinya)? Mungkin sesuatu yang lebih jelas adalah menggunakan beberapa varian kerjash -c ">"
daripadatee
.sponge
adalah bagian darimoreutils
paket di hampir setiap distribusi kecuali distro berbasis Debian.moreutils
memiliki beberapa alat yang cukup bagus yang setara dengan alat yang lebih umum sepertixargs
dantee
.cat
berjalan sebagai root, dan output diarahkan oleh shell, yang tidak berjalan sebagai root. Itu sama denganecho hi > /read/only/file
.Di baris perintah yang dieksekusi,
%
singkatan dari nama file saat ini . Ini didokumentasikan dalam:help cmdline-special
:Seperti yang sudah Anda ketahui,
:w !cmd
pipa konten buffer saat ini ke perintah lain. Apa yangtee
dilakukan adalah menyalin input standar ke satu atau lebih file, dan juga ke output standar. Oleh karena itu,:w !sudo tee % > /dev/null
secara efektif menulis isi buffer saat ini ke file saat ini sambil menjadi root . Perintah lain yang dapat digunakan untuk ini adalahdd
:Sebagai pintasan, Anda dapat menambahkan pemetaan ini ke
.vimrc
:Dengan di atas Anda bisa mengetik
:w!!<Enter>
untuk menyimpan file sebagai root.sumber
:help _%
memunculkan apa yang Anda masukkan, tetapi:help %
menampilkan kunci pencocokan penjepit. Saya tidak akan berpikir untuk mencoba awalan garis bawah, apakah itu semacam pola dalam dokumentasi vim? Apakah ada hal-hal 'khusus' lainnya untuk dicoba ketika mencari bantuan?help
Perintah melompat ke sebuah tag. Anda dapat melihat tag yang tersedia dengan:h help-tags
. Anda juga dapat menggunakan penyelesaian baris perintah untuk melihat tag yang cocok::h cmdline<Ctrl-D>
(atau:h cmdline<Tab>
jika Anda mengaturnya denganwildmode
tepat)cmap w!! w !sudo tee % > /dev/null
file .vimrc saya untuk membuat ini berfungsi. Apakah jawaban yang%
salah dalam jawaban di atas? (Tidak ada pakar vim di sini.)sudo tee > /dev/null /path/to/current/file
yang tidak masuk akal. (Akan mengeditnya)Ini juga berfungsi dengan baik:
Ini terinspirasi oleh komentar @Nathan Long.
MEMPERHATIKAN :
"
harus digunakan alih-alih'
karena kami ingin%
diperluas sebelum meneruskan ke shell.sumber
tee
dengan/usr/bin/tee
untuk mencegah serangan modifikasi PATH.:w
- Tulis file.!sudo
- Panggil perintah sudo shell.tee
- Output dari perintah write (vim: w) dialihkan menggunakan tee. % Tidak lain adalah nama file saat ini yaitu /etc/apache2/conf.d/mediawiki.conf. Dengan kata lain perintah tee dijalankan sebagai root dan dibutuhkan input standar dan menulisnya ke file yang diwakili oleh%. Namun, ini akan meminta untuk memuat ulang file lagi (tekan L untuk memuat perubahan di vim itu sendiri):tautan tutorial
sumber
Jawaban yang diterima mencakup semuanya, jadi saya hanya akan memberikan contoh cara pintas lainnya yang saya gunakan, sebagai catatan.
Tambahkan ke
etc/vim/vimrc
(atau~/.vimrc
):cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
Dimana:
cnoremap
: memberitahu vim bahwa pintasan berikut harus dikaitkan di baris perintah.w!!
: pintasan itu sendiri.execute '...'
: perintah yang menjalankan string berikut.silent!
: jalankan secara diam-diamwrite !sudo tee % >/dev/null
: pertanyaan OP, menambahkan pengalihan pesanNULL
untuk membuat perintah bersih<bar> edit!
: Trik ini adalah cherry of the cake: ia juga memanggiledit
perintah untuk memuat ulang buffer dan kemudian menghindari pesan seperti buffer telah berubah .<bar>
adalah cara menulis simbol pipa untuk memisahkan dua perintah di sini.Semoga ini bisa membantu. Lihat juga untuk masalah lain:
sumber
Saya ingin menyarankan pendekatan lain untuk "Oups saya lupa menulis
sudo
saat membuka file saya" :Alih-alih menerima
permission denied
, dan harus mengetik:w!!
, saya merasa lebih elegan untuk memilikivim
perintah kondisional yang dilakukansudo vim
jika pemilik fileroot
.Ini semudah diimplementasikan (bahkan mungkin ada implementasi yang lebih elegan, saya jelas bukan bash-guru):
Dan itu bekerja dengan sangat baik.
Ini adalah pendekatan yang lebih
bash
terpusat daripada avim
-satu jadi tidak semua orang mungkin menyukainya.Tentu saja:
root
tetapi membutuhkansudo
, tetapi fungsi tetap dapat diedit)vim
untuk membaca-hanya file (sejauh yang saya ketahui, saya menggunakantail
ataucat
untuk file kecil)Tapi saya menemukan ini membawa pengalaman pengguna dev yang jauh lebih baik , yang merupakan sesuatu yang cenderung dilupakan IMHO ketika menggunakan
bash
. :-)sumber
root
kata sandi dipertanyakan.UNTUK NEOVIM
Karena ada masalah dengan panggilan interaktif ( https://github.com/neovim/neovim/issues/1716 ), saya menggunakan ini untuk neovim, berdasarkan jawaban Dr Beco:
Ini akan membuka dialog menggunakan
ssh-askpass
menanyakan kata sandi sudo.sumber