Pertanyaan Bagaimana cara kerja vim "tulis dengan sudo"?


Banyak dari Anda mungkin telah melihat perintah yang memungkinkan Anda menulis pada file yang memerlukan izin root, bahkan ketika Anda lupa membuka vim dengan sudo:

:w !sudo tee %

Masalahnya adalah saya tidak mendapatkan apa yang sebenarnya terjadi di sini.

Saya sudah menemukan 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 garis sebagai input standar.

Itu !sudo tee panggilan sebagian tee dengan hak administrator.

Untuk semua masuk akal, itu % 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?


1148
2018-04-08 14:36


asal


Jawaban:


% berarti "file saat ini"

Sebagai eugene y menunjukkan, % memang berarti "nama file saat ini". Penggunaan lain untuk ini di Vim adalah dalam perintah substitusi. Sebagai contoh, :%s/foo/bar berarti "dalam file saat ini, ganti kejadian foo dengan bar. "Jika Anda menyorot beberapa teks sebelum mengetik :s, Anda akan melihat bahwa garis yang disorot mengambil tempat % sebagai rentang substitusi Anda.

:w tidak memperbarui file Anda

Satu bagian yang membingungkan dari trik ini adalah Anda mungkin berpikir :w sedang memodifikasi file Anda, tetapi sebenarnya tidak. Jika Anda membuka dan memodifikasi file1.txt, lalu berlari :w file2.txt, itu akan menjadi "save as"; file1.txt tidak akan dimodifikasi, tetapi konten buffer saat ini akan dikirim ke file2.txt.

Dari pada file2.txt, kamu bisa mengganti perintah shell untuk menerima isi buffer. Contohnya, :w !cat hanya akan menampilkan isinya.

Jika Vim tidak dijalankan dengan akses sudo, itu :w tidak dapat memodifikasi file yang dilindungi, tetapi jika melewati konten buffer ke shell, sebuah perintah di shell bisa dijalankan dengan sudo. Dalam hal ini, kami menggunakan tee.

Memahami tee

Seperti untuk tee, gambar tee perintah sebagai pipa berbentuk T dalam situasi bash piping normal: mengarahkan output ke file yang ditentukan (s) dan juga mengirimkannya ke output standar, yang dapat ditangkap oleh perintah pipan berikutnya.

Misalnya, di ps -ax | tee processes.txt | grep 'foo', daftar proses akan ditulis ke file teks dan diteruskan ke grep.

     +-----------+    tee     +------------+
     |           |  --------  |            |
     | ps -ax    |  --------  | grep 'foo' |
     |           |     ||     |            |
     +-----------+     ||     +------------+
                       ||   
               +---------------+
               |               |
               | processes.txt |
               |               |
               +---------------+

(Diagram dibuat dengan Asciiflow.)

Lihat tee halaman manual untuk info lebih lanjut.

Tee sebagai hack

Dalam situasi yang dijelaskan pertanyaan Anda, menggunakan tee adalah peretasan karena kami mengabaikan setengah dari apa yang dilakukannya. sudo tee menulis ke file kami dan juga mengirimkan konten buffer ke output standar, tetapi kami mengabaikan output standar. Kita tidak perlu melewatkan apa pun ke perintah piped lain dalam kasus ini; kami hanya menggunakan tee sebagai cara alternatif menulis file dan sehingga kita bisa menyebutnya dengan sudo.

Membuat trik ini mudah

Anda dapat menambahkan ini ke Anda .vimrc untuk membuat trik ini mudah digunakan: ketikkan saja :w!!.

" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %

Itu > /dev/nullbagian secara eksplisit membuang output standar, karena, seperti yang saya katakan, kita tidak perlu melewatkan apapun ke perintah piped lain.


1272
2017-08-16 12:49



Di baris perintah yang dieksekusi, % singkatan dari nama file saat ini. Ini didokumentasikan dalam :help cmdline-special:

In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
        %       Is replaced with the current file name.

Seperti yang sudah Anda temukan, :w !cmd menyalurkan isi buffer saat ini ke perintah lain. Apa tee yang dilakukan adalah menyalin input standar ke satu atau lebih file, dan juga ke output standar. Karena itu, :w !sudo tee % > /dev/null efektif menulis isi buffer saat ini ke file saat ini sementara menjadi root. Perintah lain yang bisa digunakan untuk ini adalah dd:

:w !sudo dd of=% > /dev/null

Sebagai pintasan, Anda dapat menambahkan pemetaan ini ke Anda .vimrc:

" Force saving files that require root permission 
cnoremap w!! w !sudo tee > /dev/null %

Dengan cara di atas Anda dapat mengetik :w!!<Enter> untuk menyimpan file sebagai root.


88
2018-04-08 14:45



Ini juga berfungsi dengan baik:

:w !sudo sh -c "cat > %"

Ini terinspirasi oleh komentar @Nathan Long.

MELIHAT:

" harus digunakan sebagai ganti ' karena kami mau % untuk diperluas sebelum melewati ke shell.


18
2017-07-29 08:08



:w - Tulis file.

!sudo - Panggil perintah shell sudo.

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 ia mengambil input standar dan menuliskannya ke sebuah file yang diwakili oleh%. Namun, ini akan meminta untuk memuat ulang file lagi (tekan L untuk memuat perubahan di vim itu sendiri):

tautan tutorial


16
2018-06-04 06:02



Jawaban yang diterima mencakup semuanya, jadi saya akan memberikan contoh lain dari a jalan pintas yang saya gunakan, sebagai catatan.

Tambahkan ke Anda 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 dalam baris perintah.
  • w!!: pintas itu sendiri.
  • execute '...': perintah yang mengeksekusi string berikut.
  • silent!: jalankan diam-diam
  • write !sudo tee % >/dev/null: pertanyaan OP, menambahkan pengalihan pesan ke NULL untuk membuat perintah yang bersih
  • <bar> edit!: trik ini adalah ceri kue: itu juga panggilan edit perintah untuk memuat kembali buffer dan kemudian hindari pesan seperti buffer telah berubah. <bar> adalah cara menulis pipa simbol untuk memisahkan dua perintah di sini.

Semoga itu membantu. Lihat juga untuk masalah lain:


3
2018-01-13 07:12



Saya ingin menyarankan pendekatan lain untuk "Oups saya lupa menulis sudo saat membuka file saya " isu:

Alih-alih menerima permission denied, dan harus mengetik :w!!, Saya merasa lebih elegan untuk memiliki bersyarat vim perintah itu sudo vim jika pemilik file root.

Ini mudah diterapkan (bahkan mungkin ada penerapan yang lebih elegan, saya jelas bukan bash-guru):

function vim(){
  OWNER=$(stat -c '%U' $1)
  if [[ "$OWNER" == "root" ]]; then
    sudo /usr/bin/vim $*;
  else
    /usr/bin/vim $*;
  fi
}

Dan itu bekerja dengan sangat baik.

Ini lebih banyak bashpendekatan yang dipusatkan dari a vim-Satu jadi tidak semua orang mungkin menyukainya.

Tentu saja:

  • ada kasus penggunaan di mana ia akan gagal (ketika pemilik file tidak root tetapi membutuhkan sudo, tetapi fungsinya tetap dapat diedit)
  • itu tidak masuk akal ketika menggunakan vim untuk membaca-hanya file (sejauh yang saya ketahui, saya gunakan tail atau cat untuk file kecil)

Tapi saya menemukan ini membawa jauh lebih baik pengalaman pengguna dev, sesuatu yang IMHO cenderung dilupakan saat menggunakan bash. :-)


1
2018-02-28 18:21