apa yang setara dengan zsh dari ekspor -f bash


24

Jadi saya mulai menggunakan zsh. Saya suka semuanya. Tampaknya sangat keren dan apik, dan fakta bahwa direktori kerja saat ini dan baris perintah aktual pada baris yang berbeda adalah baik, tetapi pada saat yang sama, saya memperhatikan bahwa itu zshbisa sedikit lebih lambat daripada bash, terutama ketika mencetak teks ke layar.

Hal yang paling saya sukai adalah fakta bahwa zsh'kompatibel dengan' semua fungsi yang saya definisikan di .bashrc.

Namun satu keluhan. Semua fungsinya bekerja dengan sempurna, tapi saya tidak tahu cara kerja sistem ekspor.

Saya memiliki beberapa .bashrcfungsi yang diekspor sehingga saya dapat menggunakannya di tempat lain, seperti dalam skrip dan program eksternal export -f.

Di zsh, ekspor sepertinya tidak dibicarakan. Apakah ini autoloading? Apakah kedua hal itu sama? Saya mengalami kesulitan serius mencari tahu itu.


2
Ini adalah pertanyaan yang sangat lama, tetapi saya ingin mengatakan bahwa "direktori kerja saat ini dan baris perintah aktual ada pada baris yang berbeda" sama sekali tidak ada hubungannya dengan zsh. Itu tergantung pada bagaimana Anda mengatur prompt Anda, itu saja.
4ae1e1

Jawaban:


11

Variabel lingkungan yang mengandung fungsi adalah bash hack. Zsh tidak memiliki yang serupa. Anda dapat melakukan sesuatu yang serupa dengan beberapa baris kode. Variabel lingkungan mengandung string; versi bash yang lebih lama, sebelum Shellshock ditemukan, menyimpan kode fungsi dalam variabel yang namanya adalah fungsi dan yang nilainya () {diikuti oleh kode fungsi diikuti oleh }. Anda dapat menggunakan kode berikut untuk mengimpor variabel dengan penyandian ini, dan mencoba menjalankannya dengan pengaturan mirip-bash. Perhatikan bahwa zsh tidak dapat mengemulasi semua fitur bash, yang dapat Anda lakukan adalah sedikit lebih dekat (mis. Untuk $foomemisahkan nilai dan memperluas wildcard, dan membuat array berbasis 0).

bash_function_preamble='
    emulate -LR ksh
'
for name in ${(k)parameters}; do
  [[ "-$parameters[name]-" = *-export-* ]] || continue
  [[ ${(P)name} = '() {'*'}' ]] || continue
  ((! $+builtins[$name])) || continue
  functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done

(Seperti Stéphane Chazelas , penemu asli Shellshock, mencatat, versi sebelumnya dari jawaban ini dapat mengeksekusi kode arbitrer pada titik ini jika definisi fungsi salah. Versi ini tidak, tetapi tentu saja begitu Anda menjalankan perintah, bisa jadi fungsi yang diimpor dari lingkungan.)

Versi Post-Shellshock dari fungsi bash encode di lingkungan menggunakan nama variabel yang tidak valid (misalnya BASH_FUNC_myfunc%%). Ini membuat mereka lebih sulit untuk menguraikan dengan andal karena zsh tidak menyediakan antarmuka untuk mengekstrak nama variabel seperti itu dari lingkungan.

Saya tidak merekomendasikan melakukan ini. Mengandalkan fungsi yang diekspor dalam skrip adalah ide yang buruk: itu menciptakan ketergantungan yang tidak terlihat dalam skrip Anda. Jika Anda pernah menjalankan skrip Anda di lingkungan yang tidak memiliki fungsi Anda (di komputer lain, dalam tugas cron, setelah mengubah file inisialisasi shell Anda, ...), skrip Anda tidak akan berfungsi lagi. Alih-alih, simpan semua fungsi Anda dalam satu atau beberapa file terpisah (seperti ~/lib/shell/foo.sh) dan mulai skrip Anda dengan mengimpor fungsi yang digunakannya ( . ~/lib/shell/foo.sh). Dengan cara ini, jika Anda memodifikasi foo.sh, Anda dapat dengan mudah mencari skrip mana yang bergantung padanya. Jika Anda menyalin skrip, Anda dapat dengan mudah menemukan file tambahan yang dibutuhkan.

Zsh (dan ksh sebelum itu) membuat ini lebih nyaman dengan menyediakan cara untuk memuat fungsi secara otomatis dalam skrip di mana mereka digunakan. Batasannya adalah Anda hanya dapat menempatkan satu fungsi per file. Deklarasikan fungsi sebagai autoloaded, dan letakkan definisi fungsi dalam file yang namanya adalah nama fungsi. Masukkan file ini ke direktori yang terdaftar $fpath(yang dapat Anda konfigurasikan melalui FPATHvariabel lingkungan). Dalam skrip Anda, deklarasikan fungsi-fungsi yang diisi-otomatis dengan autoload -U foo.

Selanjutnya zsh dapat mengkompilasi skrip, untuk menghemat waktu parsing. Panggil zcompileuntuk menyusun skrip. Ini menciptakan file dengan .zwcekstensi. Jika file ini ada maka autoloadakan memuat file yang dikompilasi alih-alih kode sumber. Anda dapat menggunakan zrecompilefungsi untuk (mengkompilasi) semua definisi fungsi dalam direktori.


1
Lucu bagaimana kode Anda memiliki kerentanan shellshock yang sama bash(tidak memverifikasi bahwa konten variabel hanya definisi fungsi dan memproses nama variabel seperti HTTP_HOSTatau LC_X). Jawaban yang bagus sebaliknya.
Stéphane Chazelas

@ StéphaneChazelas Jika Anda akan menjalankan perintah dengan fungsi yang diimpor dari lingkungan, Anda kehilangan banyak hal. Tetapi saya telah memperbarui kode impor untuk tidak menjalankan kode arbitrer. Ini tidak terlalu berguna, karena bash post-shellshock tidak menyandikan fungsi yang diekspor dengan cara yang sama.
Gilles 'SANGAT berhenti menjadi jahat'

Anda sekarang telah memperbaiki setara dengan CVE-2014-6271, tetapi masih mungkin terkena banyak kerentanan dari tipe CVE-2014-6277 / 6278 ... karena Anda masih mengekspos parser zsh untuk kode dalam variabel apa pun termasuk beberapa yang berpotensi di bawah kendali penyerang dalam beberapa konteks (seperti kode zsh -c 'functions[f]=$VAR' yang diurai bahkan jika ffungsi tidak pernah disebut). Solusinya adalah dengan mempertimbangkan hanya variabel yang namanya mengikuti templat yang dicadangkan seperti itu $BASH_FUNC_x%%, tetapi seperti yang Anda katakan, zshtidak memiliki API untuk mendaftar atau mengambilnya. Anda harus menelepon perlmisalnya.
Stéphane Chazelas

7

Jika Anda menempatkan deklarasi fungsi Anda di .zshenv , fungsi Anda akan dapat digunakan dari skrip tanpa upaya apa pun.


Mengapa Anda menurunkan jawaban saya? Tolong jelaskan.
rools

Masih menunggu jawaban dan masih bekerja!
rools

Saya baru saja menemukan jawaban ini dan ini adalah solusi ideal.
AFH

Saya tidak mencatatnya. Dan TBH OP bertanya tentang mengekspor barang dari .bashrc, yang merupakan ide yang buruk, lebih baik untuk memasukkannya ke dalam skrip sehingga Anda tidak berakhir dengan lingkungan yang besar. Tapi solusi Anda hanyalah varian dari ide buruk yang sama, masukkan semua skrip Anda .zshenvdan memperlambat setiap permintaan zsh dengan mem-parsing banyak kode yang tidak pernah digunakan. Lebih jauh itu tidak sama dengan mengekspor suatu fungsi, seperti halnya variabel yang diekspor, fungsi yang diekspor hanya tersedia untuk proses anak. Sedangkan barang yang Anda masukkan .zshenvtersedia untuk setiap zsh.
Metamorphic

Akhirnya jika Anda mengandalkan kode pribadi yang Anda masukkan ke dalam .zshenv, maka semua skrip Anda akan sepenuhnya non-portabel. Biasanya skrip bisa saling bergantung, yang baik-baik saja, Anda bagikan bersama. Tetapi jika mereka bergantung pada memiliki fungsi khusus .zshenv, tidak ada yang mau menggunakannya, atau mereka harus dipanggil dengan khusus ZDOTDIR, mencegah Anda sendiri .zshenvdieksekusi. Itu akan menyebalkan.
Metamorphic
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.