Saya mencoba yang berikut tetapi sepertinya tidak berhasil:
$ cat script.sh
#!/bin/env -i /bin/sh
/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.
bash
shell-script
env
balki
sumber
sumber
Jawaban:
Alasan ini tidak berhasil adalah karena ia melihat
-i /bin/sh
sebagai argumen tunggalenv
. Biasanya ini akan menjadi 2 argumen,-i
dan/bin/sh
. Ini hanyalah batasan dari shebang. Tidak ada jalan lain.Namun Anda masih dapat melakukan tugas ini, hanya dengan cara yang berbeda.
Jika Anda ingin tugas ini dilakukan oleh skrip itu sendiri, dan tidak harus melakukan sesuatu seperti
env -i script.sh
, Anda dapat meminta skrip dijalankan kembali.Ini akan menyebabkan skrip untuk mengeksekusi ulang dirinya sendiri jika
CLEANED
variabel lingkungan tidak diatur. Kemudian pada re-exec, ia menetapkan variabel untuk memastikan bahwa itu tidak masuk ke loop.sumber
env
dari GNU coreutils sekarang memiliki opsi-S
untuk menyelesaikan masalah yang mirip dengan yang satu ini tetapi tidak persis sama. Sebagai contoh#!/usr/bin/env -S perl -T
.#!/usr/bin/env -S -i /bin/sh
. Waspadai masalah portabilitas.Jalankan skrip Anda dengan
env -i
:Dan skrip seperti biasa:
Jika Anda bermaksud untuk menjalankan dengan lingkungan yang bersih tanpa secara eksplisit mengatakan bahwa ketika Anda menjalankan. Eduardo Ivanec memberikan beberapa ide dalam jawaban ini , Anda dapat memanggil skrip Anda secara rekursif
exec
ketika lingkungan tidak bersih (mis. $ HOME didefinisikan):sumber
Dengan bash, Anda dapat melakukannya seperti ini:
The
set -e
danset -u
perintah tidak benar-benar diperlukan, tapi saya termasuk mereka untuk menunjukkan bahwa pendekatan ini tidak bergantung pada mengakses variabel unset (sebagai misalnya[ "$HOME" != "" ]
akan) dan kompatibel denganset -e
pengaturan.Pengujian
HOME
variabel harus aman karena bash mengeksekusi skrip dalam mode non-interaktif, yaitu file konfigurasi seperti~/.bashrc
(di mana variabel lingkungan dapat diatur) tidak bersumber selama startup.Contoh output:
sumber
Sayangnya itu tidak akan bekerja seperti itu - Linux menganggap
-i /bin/sh
sebagai satu argumen untuk diteruskan keenv
(lihat Shebang ).sumber
Batasan shebang 2-argumen Linux (interpeter + argumen tunggal) dicatat di sebagian besar jawaban, tetapi untuk mengatakan ini tidak dapat dilakukan adalah salah - Anda hanya perlu mengubah ke penerjemah yang dapat melakukan sesuatu yang berguna dengan satu argumen:
Apa yang dilakukan adalah dipanggil
perl
dengan skrip satu baris (-e
) yang menghapus%ENV
(lebih murah darienv -i
) dan memanggilexec /bin/sh
, dengan tepat mengutip argumen.perl
Logika lebih lanjut dapat ditambahkan, jika diperlukan (meskipun tidak banyak di Linux karena Anda terbatasBINPRM_BUF_SIZE
karakter, yang kemungkinan 128)Sayangnya, ini adalah Linux khusus, ini tidak akan bekerja pada sistem yang memungkinkan beberapa argumen shebang: - /
perl
memproses string ini sebagai argumen tunggal, jadi itu tidak dikutip di atas seperti yang biasa Anda lakukan denganperl -e ...
dari baris perintah (jika Anda menambahkan tanda kutip ini dipertahankan, perl melihat hanya string literal, dengan peringatan di atasnya akan mengeluh tentang tidak berguna konstan).Juga perhatikan ada sedikit perubahan dalam perilaku ketika digunakan dengan cara ini,
@ARGV
biasanya hanya berisi argumen, dan$0
berisi skrip, tetapi dengan shebang ini$ARGV[0]
adalah nama skrip (dan$0
sedang-e
) yang membuatnya sedikit lebih mudah.Anda juga dapat menyelesaikan ini dengan penerjemah yang "memproses ulang" baris perintahnya (tanpa
-c
argumen tambahan ) yang dilakukan oleh AT&T kunoksh93
:meskipun mungkin
ksh
tidak biasa sekarang ;-)(
bash
memiliki fitur serupa dengan--wordexp
, tetapi "tidak terdokumentasi" dalam versi di mana ia bekerja, dan tidak diaktifkan pada waktu kompilasi dalam versi yang didokumentasikan: - / Ini juga tidak dapat digunakan untuk ini karena memerlukan dua argumen. ..)Juga, secara efektif variasi jawaban @Patrick dan @ maxschlepzig:
Daripada menggunakan variabel baru, ini menggunakan "
_
" variabel khusus, jika tidak disetel persis "bash" kemudian ganti skrip denganexec
menggunakan-a
untuk membuatARGV[0]
(dan karenanya$_
) hanya "bash", dan gunakan-c
untuk membersihkan lingkungan.Atau, jika dapat diterima untuk membersihkan lingkungan di awal skrip (hanya bash):
Itu menggunakan
compgen
(pembantu penyelesaian) untuk mendaftar nama-nama semua variabel lingkungan yang diekspor, danunset
s mereka dalam satu pergi.Lihat juga Beberapa argumen di shebang untuk detail lebih lanjut tentang masalah umum perilaku shebang.
sumber