Siapa yang dapat memberi tahu saya mengapa pertanyaan ini ditutup, "terkait dengan pemrograman atau pengembangan perangkat lunak"?
tarrsalah
1
Saya setuju bahwa ini bukan di luar topik, tetapi mungkin merupakan duplikat dari beberapa pertanyaan lain seperti ini .
Keith Thompson
16
Pertanyaan ini seharusnya tidak ditandai sebagai di luar topik. Hanya perlu 5 orang dengan skor di atas 3.000 untuk menandainya sebagai "pada topik" dan dapat dibuka kembali. Ini adalah pertanyaan - khususnya tentang pemrograman.
Menjalankan melalui perintah /usr/bin/envmemiliki manfaat mencari apa pun versi default dari program ini adalah di saat env ironment.
Dengan cara ini, Anda tidak perlu mencarinya di tempat tertentu pada sistem, karena jalur tersebut mungkin berada di lokasi yang berbeda di sistem yang berbeda. Selama itu di jalan Anda, itu akan menemukannya.
Salah satu kelemahannya adalah Anda tidak akan dapat melewati lebih dari satu argumen (mis. Anda tidak akan bisa menulis /usr/bin/env awk -f) jika Anda ingin mendukung Linux, karena POSIX tidak jelas tentang bagaimana garis harus ditafsirkan, dan Linux menginterpretasikan semuanya setelah yang pertama. ruang untuk menunjukkan satu argumen. Anda dapat menggunakan /usr/bin/env -Sbeberapa versi envuntuk menyiasatinya, tetapi skrip tersebut akan menjadi semakin portabel dan rusak pada sistem yang cukup baru (mis. Bahkan Ubuntu 16.04 jika tidak lebih baru).
Kelemahan lain adalah bahwa karena Anda tidak memanggil executable eksplisit, itu punya potensi kesalahan, dan pada masalah keamanan sistem multi-pengguna (jika seseorang berhasil mendapatkan executable mereka dipanggil bashdi jalur Anda, misalnya).
#!/usr/bin/env bash #lends you some flexibility on different systems#!/usr/bin/bash #gives you explicit control on a given system of what executable is called
Dalam beberapa situasi, yang pertama mungkin lebih disukai (seperti menjalankan skrip python dengan beberapa versi python, tanpa harus mengerjakan ulang baris yang dapat dieksekusi). Tetapi dalam situasi di mana keamanan adalah fokus, yang terakhir lebih disukai, karena membatasi kemungkinan injeksi kode.
Kelemahan lainnya adalah Anda tidak bisa memberikan argumen tambahan kepada juru bahasa.
Keith Thompson
1
@KeithThompson: Info salah. Anda dapat meneruskan opsi ke juru bahasa yang mendasarinya menggunakan / usr / bin / env!
Gaurav Agarwal
4
@GauravAgarwal: Tidak di sistem saya. Sebuah script yang berisi hanya satu baris ini: #!/usr/bin/env echo Hellomengeluh: /usr/bin/env: echo Hello: No such file or directory. Rupanya itu berlaku echo Hellosebagai argumen tunggal /usr/bin/env.
Keith Thompson
1
@ AndréLaszlo: envPerintah ini tentu saja memungkinkan argumen untuk diteruskan ke perintah. Masalahnya adalah semantik #!baris, dan itu tergantung pada kernel. Kernel Linux terbaru memang memungkinkan hal-hal seperti #!/usr/bin/env command args, tetapi kernel Linux yang lebih tua dan sistem lainnya tidak.
Keith Thompson
1
Mengapa ada backticks di blok kode? Bukankah mereka harus dihapus?
Benjamin W.
64
Menggunakan #!/usr/bin/env NAMEmembuat shell mencari kecocokan pertama NAME dalam variabel lingkungan $ PATH. Ini bisa bermanfaat jika Anda tidak mengetahui jalan absolut atau tidak ingin mencarinya.
Jawaban yang sangat bagus. Jelaskan dengan singkat apa yang dilakukan env shebang, alih-alih mengatakan "pilih program berdasarkan konfigurasi sistem Anda"
De Novo
13
Alih-alih secara eksplisit mendefinisikan jalur ke penerjemah seperti di /usr/bin/bash/, dengan menggunakan perintah env, penerjemah dicari dan diluncurkan dari mana pun pertama kali ditemukan. Ini memiliki kelebihan dan kekurangan
Pada kebanyakan sistem, mereka akan secara fungsional sama, tetapi itu tergantung pada lokasi executable bash dan env Anda. Namun, tidak yakin bagaimana ini akan memengaruhi variabel lingkungan.
safay
2
"Adalah mungkin untuk menentukan penerjemah tanpa menggunakan env, dengan memberikan path lengkap ke penerjemah. Masalahnya adalah bahwa pada sistem komputer yang berbeda, jalur yang tepat mungkin berbeda. Dengan menggunakan env, penerjemah dicari dan terletak di saat skrip dijalankan. Skrip ini membuat lebih portabel, tetapi juga meningkatkan risiko bahwa penerjemah yang salah dipilih karena mencari kecocokan di setiap direktori di jalur pencarian yang dapat dieksekusi. Skrip ini juga mengalami masalah yang sama yaitu jalur ke biner env juga mungkin berbeda berdasarkan per-mesin. "- Wikipedia
Mike Clark
10
Jika skrip shell mulai dengan #!/bin/bash, mereka akan selalu dijalankan dengan bashdari /bin. Jika mereka Namun mulai dengan #!/usr/bin/env bash, mereka akan mencari bashdi $PATHdan kemudian mulai dengan yang pertama mereka dapat menemukan.
Mengapa ini berguna? Asumsikan Anda ingin menjalankan bashskrip, yang memerlukan bash 4.x atau lebih baru, namun sistem Anda hanya memiliki bash3.x diinstal dan saat ini distribusi Anda tidak menawarkan versi yang lebih baru atau Anda bukan administrator dan tidak dapat mengubah apa yang diinstal pada sistem itu .
Tentu saja, Anda dapat mengunduh kode sumber bash dan membangun bash Anda sendiri dari awal, ~/binmisalnya sebagai contoh. Dan Anda juga dapat memodifikasi $PATHvariabel Anda di .bash_profilefile Anda untuk dimasukkan ~/binsebagai entri pertama ( PATH=$HOME/bin:$PATHkarena ~tidak akan diperluas dalam $PATH). Jika sekarang Anda menelepon bash, shell pertama-tama akan mencarinya secara $PATHberurutan, jadi itu dimulai dengan ~/bin, di mana ia akan menemukan bash. Hal yang sama terjadi jika skrip mencari bashmenggunakan #!/usr/bin/env bash, jadi skrip ini sekarang akan bekerja pada sistem Anda menggunakan custom bashbuild Anda.
Salah satu kelemahannya adalah, hal ini dapat menyebabkan perilaku yang tidak terduga, misalnya skrip yang sama pada mesin yang sama dapat berjalan dengan penerjemah berbeda untuk lingkungan yang berbeda atau pengguna dengan jalur pencarian yang berbeda, menyebabkan semua jenis sakit kepala.
Kelemahan terbesar envadalah bahwa beberapa sistem hanya akan mengizinkan satu argumen, jadi Anda tidak dapat melakukan ini #!/usr/bin/env <interpreter> <arg>, karena sistem akan melihat <interpreter> <arg>sebagai satu argumen (mereka akan memperlakukannya seolah-olah ungkapan itu dikutip) dan dengan demikian envakan mencari nama juru bahasa <interpreter> <arg>. Perhatikan bahwa ini bukan masalah envperintah itu sendiri, yang selalu memungkinkan beberapa parameter dilewati tetapi dengan parser shebang dari sistem yang mem-parsing baris ini sebelum bahkan memanggil env. Sementara ini telah diperbaiki pada sebagian besar sistem tetapi jika skrip Anda ingin menjadi sangat portabel, Anda tidak dapat mengandalkan bahwa ini telah diperbaiki pada sistem yang akan Anda jalankan.
Ia bahkan dapat memiliki implikasi keamanan, misalnya jika sudotidak dikonfigurasi untuk membersihkan lingkungan atau $PATHdikeluarkan dari pembersihan. Biarkan saya menunjukkan ini:
Biasanya /binadalah tempat yang terlindungi dengan baik, hanya rootdapat mengubah apa pun di sana. Direktori rumah Anda tidak, bagaimanapun, program apa pun yang Anda jalankan dapat membuat perubahan padanya. Itu berarti kode jahat dapat menempatkan palsu bashke beberapa direktori tersembunyi, memodifikasi Anda .bash_profileuntuk memasukkan direktori itu di Anda $PATH, sehingga semua skrip yang menggunakan #!/usr/bin/env bashakhirnya akan berjalan dengan palsu itu bash. Jika sudoterus $PATH, Anda dalam masalah besar.
Misalnya, pertimbangkan alat membuat file ~/.evil/bashdengan konten berikut:
#!/bin/bashif[ $EUID -eq 0];then
echo "All your base are belong to us..."# We are root - do whatever you want to dofi/bin/bash "$@"
Mari kita membuat skrip sederhana sample.sh:
#!/usr/bin/env bash
echo "Hello World"
Bukti konsep (pada sistem tempat sudomenyimpan $PATH):
$ ./sample.sh
Hello World
$ sudo ./sample.sh
Hello World
$ export PATH="$HOME/.evil:$PATH"
$ ./sample.sh
Hello World
$ sudo ./sample.sh
All your base are belong to us...
Hello World
Biasanya semua shell klasik harus ditempatkan di /bindan jika Anda tidak ingin menempatkannya di sana untuk alasan apa pun, itu benar-benar bukan masalah untuk menempatkan symlink di /binyang menunjuk ke lokasi mereka yang sebenarnya (atau mungkin /binitu sendiri adalah symlink), jadi Saya akan selalu pergi dengan #!/bin/shdan #!/bin/bash. Ada terlalu banyak yang akan rusak jika ini tidak berfungsi lagi. Bukan berarti POSIX akan membutuhkan posisi ini (POSIX tidak membakukan nama jalur dan dengan demikian bahkan tidak menstandardisasi fitur shebang sama sekali) tetapi mereka sangat umum, bahwa bahkan jika suatu sistem tidak menawarkan /bin/sh, mungkin masih akan mengerti #!/bin/shdan tahu apa yang harus dilakukan dengannya dan mungkin hanya untuk kompatibilitas dengan kode yang ada.
Tetapi untuk penerjemah yang lebih modern, non standar, opsional seperti Perl, PHP, Python, atau Ruby, itu tidak benar-benar ditentukan di mana pun di mana mereka seharusnya berada. Mereka mungkin dalam /usr/bintetapi mereka mungkin juga berada di /usr/local/binatau di cabang hirarki yang sama sekali berbeda ( /opt/..., /Applications/..., dll). Itu sebabnya ini sering menggunakan #!/usr/bin/env xxxsintaks shebang.
Saya merasa ini berguna, karena ketika saya tidak tahu tentang env, sebelum saya mulai menulis skrip saya melakukan ini:
type nodejs > scriptname.js #or any other environment
dan kemudian saya memodifikasi baris dalam file ke shebang.
Saya melakukan ini, karena saya tidak selalu ingat di mana nodejs di komputer saya - / usr / bin / atau / bin /, jadi bagi saya envsangat berguna. Mungkin ada detail dengan ini, tapi ini alasan saya
Jawaban:
Menjalankan melalui perintah
/usr/bin/env
memiliki manfaat mencari apa pun versi default dari program ini adalah di saat env ironment.Dengan cara ini, Anda tidak perlu mencarinya di tempat tertentu pada sistem, karena jalur tersebut mungkin berada di lokasi yang berbeda di sistem yang berbeda. Selama itu di jalan Anda, itu akan menemukannya.
Salah satu kelemahannya adalah Anda tidak akan dapat melewati lebih dari satu argumen (mis. Anda tidak akan bisa menulis
/usr/bin/env awk -f
) jika Anda ingin mendukung Linux, karena POSIX tidak jelas tentang bagaimana garis harus ditafsirkan, dan Linux menginterpretasikan semuanya setelah yang pertama. ruang untuk menunjukkan satu argumen. Anda dapat menggunakan/usr/bin/env -S
beberapa versienv
untuk menyiasatinya, tetapi skrip tersebut akan menjadi semakin portabel dan rusak pada sistem yang cukup baru (mis. Bahkan Ubuntu 16.04 jika tidak lebih baru).Kelemahan lain adalah bahwa karena Anda tidak memanggil executable eksplisit, itu punya potensi kesalahan, dan pada masalah keamanan sistem multi-pengguna (jika seseorang berhasil mendapatkan executable mereka dipanggil
bash
di jalur Anda, misalnya).Dalam beberapa situasi, yang pertama mungkin lebih disukai (seperti menjalankan skrip python dengan beberapa versi python, tanpa harus mengerjakan ulang baris yang dapat dieksekusi). Tetapi dalam situasi di mana keamanan adalah fokus, yang terakhir lebih disukai, karena membatasi kemungkinan injeksi kode.
sumber
#!/usr/bin/env echo Hello
mengeluh:/usr/bin/env: echo Hello: No such file or directory
. Rupanya itu berlakuecho Hello
sebagai argumen tunggal/usr/bin/env
.env
Perintah ini tentu saja memungkinkan argumen untuk diteruskan ke perintah. Masalahnya adalah semantik#!
baris, dan itu tergantung pada kernel. Kernel Linux terbaru memang memungkinkan hal-hal seperti#!/usr/bin/env command args
, tetapi kernel Linux yang lebih tua dan sistem lainnya tidak.Menggunakan
#!/usr/bin/env NAME
membuat shell mencari kecocokan pertama NAME dalam variabel lingkungan $ PATH. Ini bisa bermanfaat jika Anda tidak mengetahui jalan absolut atau tidak ingin mencarinya.sumber
Alih-alih secara eksplisit mendefinisikan jalur ke penerjemah seperti di
/usr/bin/bash/
, dengan menggunakan perintah env, penerjemah dicari dan diluncurkan dari mana pun pertama kali ditemukan. Ini memiliki kelebihan dan kekurangansumber
Jika skrip shell mulai dengan
#!/bin/bash
, mereka akan selalu dijalankan denganbash
dari/bin
. Jika mereka Namun mulai dengan#!/usr/bin/env bash
, mereka akan mencaribash
di$PATH
dan kemudian mulai dengan yang pertama mereka dapat menemukan.Mengapa ini berguna? Asumsikan Anda ingin menjalankan
bash
skrip, yang memerlukan bash 4.x atau lebih baru, namun sistem Anda hanya memilikibash
3.x diinstal dan saat ini distribusi Anda tidak menawarkan versi yang lebih baru atau Anda bukan administrator dan tidak dapat mengubah apa yang diinstal pada sistem itu .Tentu saja, Anda dapat mengunduh kode sumber bash dan membangun bash Anda sendiri dari awal,
~/bin
misalnya sebagai contoh. Dan Anda juga dapat memodifikasi$PATH
variabel Anda di.bash_profile
file Anda untuk dimasukkan~/bin
sebagai entri pertama (PATH=$HOME/bin:$PATH
karena~
tidak akan diperluas dalam$PATH
). Jika sekarang Anda meneleponbash
, shell pertama-tama akan mencarinya secara$PATH
berurutan, jadi itu dimulai dengan~/bin
, di mana ia akan menemukanbash
. Hal yang sama terjadi jika skrip mencaribash
menggunakan#!/usr/bin/env bash
, jadi skrip ini sekarang akan bekerja pada sistem Anda menggunakan custombash
build Anda.Salah satu kelemahannya adalah, hal ini dapat menyebabkan perilaku yang tidak terduga, misalnya skrip yang sama pada mesin yang sama dapat berjalan dengan penerjemah berbeda untuk lingkungan yang berbeda atau pengguna dengan jalur pencarian yang berbeda, menyebabkan semua jenis sakit kepala.
Kelemahan terbesar
env
adalah bahwa beberapa sistem hanya akan mengizinkan satu argumen, jadi Anda tidak dapat melakukan ini#!/usr/bin/env <interpreter> <arg>
, karena sistem akan melihat<interpreter> <arg>
sebagai satu argumen (mereka akan memperlakukannya seolah-olah ungkapan itu dikutip) dan dengan demikianenv
akan mencari nama juru bahasa<interpreter> <arg>
. Perhatikan bahwa ini bukan masalahenv
perintah itu sendiri, yang selalu memungkinkan beberapa parameter dilewati tetapi dengan parser shebang dari sistem yang mem-parsing baris ini sebelum bahkan memanggilenv
. Sementara ini telah diperbaiki pada sebagian besar sistem tetapi jika skrip Anda ingin menjadi sangat portabel, Anda tidak dapat mengandalkan bahwa ini telah diperbaiki pada sistem yang akan Anda jalankan.Ia bahkan dapat memiliki implikasi keamanan, misalnya jika
sudo
tidak dikonfigurasi untuk membersihkan lingkungan atau$PATH
dikeluarkan dari pembersihan. Biarkan saya menunjukkan ini:Biasanya
/bin
adalah tempat yang terlindungi dengan baik, hanyaroot
dapat mengubah apa pun di sana. Direktori rumah Anda tidak, bagaimanapun, program apa pun yang Anda jalankan dapat membuat perubahan padanya. Itu berarti kode jahat dapat menempatkan palsubash
ke beberapa direktori tersembunyi, memodifikasi Anda.bash_profile
untuk memasukkan direktori itu di Anda$PATH
, sehingga semua skrip yang menggunakan#!/usr/bin/env bash
akhirnya akan berjalan dengan palsu itubash
. Jikasudo
terus$PATH
, Anda dalam masalah besar.Misalnya, pertimbangkan alat membuat file
~/.evil/bash
dengan konten berikut:Mari kita membuat skrip sederhana
sample.sh
:Bukti konsep (pada sistem tempat
sudo
menyimpan$PATH
):Biasanya semua shell klasik harus ditempatkan di
/bin
dan jika Anda tidak ingin menempatkannya di sana untuk alasan apa pun, itu benar-benar bukan masalah untuk menempatkan symlink di/bin
yang menunjuk ke lokasi mereka yang sebenarnya (atau mungkin/bin
itu sendiri adalah symlink), jadi Saya akan selalu pergi dengan#!/bin/sh
dan#!/bin/bash
. Ada terlalu banyak yang akan rusak jika ini tidak berfungsi lagi. Bukan berarti POSIX akan membutuhkan posisi ini (POSIX tidak membakukan nama jalur dan dengan demikian bahkan tidak menstandardisasi fitur shebang sama sekali) tetapi mereka sangat umum, bahwa bahkan jika suatu sistem tidak menawarkan/bin/sh
, mungkin masih akan mengerti#!/bin/sh
dan tahu apa yang harus dilakukan dengannya dan mungkin hanya untuk kompatibilitas dengan kode yang ada.Tetapi untuk penerjemah yang lebih modern, non standar, opsional seperti Perl, PHP, Python, atau Ruby, itu tidak benar-benar ditentukan di mana pun di mana mereka seharusnya berada. Mereka mungkin dalam
/usr/bin
tetapi mereka mungkin juga berada di/usr/local/bin
atau di cabang hirarki yang sama sekali berbeda (/opt/...
,/Applications/...
, dll). Itu sebabnya ini sering menggunakan#!/usr/bin/env xxx
sintaks shebang.sumber
Saya merasa ini berguna, karena ketika saya tidak tahu tentang env, sebelum saya mulai menulis skrip saya melakukan ini:
dan kemudian saya memodifikasi baris dalam file ke shebang.
Saya melakukan ini, karena saya tidak selalu ingat di mana nodejs di komputer saya - / usr / bin / atau / bin /, jadi bagi saya
env
sangat berguna. Mungkin ada detail dengan ini, tapi ini alasan sayasumber