Saya telah melihat baris ini #!/usr/bin/env node
di awal beberapa contoh nodejs
dan saya telah mencari di Google tanpa menemukan topik apa pun yang dapat menjawab alasan baris itu.
Sifat kata-katanya membuat pencarian tidak semudah itu.
Saya akan membaca beberapa javascript
dan nodejs
buku baru-baru ini dan saya tidak ingat melihat dalam salah satu dari mereka.
Jika Anda menginginkan contoh, Anda dapat melihat tutorialRabbitMQ
resmi , mereka memilikinya di hampir semua contoh mereka, ini salah satunya:
#!/usr/bin/env node
var amqp = require('amqplib/callback_api');
amqp.connect('amqp://localhost', function(err, conn) {
conn.createChannel(function(err, ch) {
var ex = 'logs';
var msg = process.argv.slice(2).join(' ') || 'Hello World!';
ch.assertExchange(ex, 'fanout', {durable: false});
ch.publish(ex, '', new Buffer(msg));
console.log(" [x] Sent %s", msg);
});
setTimeout(function() { conn.close(); process.exit(0) }, 500);
});
Bisakah seseorang menjelaskan kepada saya apa arti baris ini?
Apa bedanya jika saya meletakkan atau menghapus baris ini? Dalam kasus apa saya membutuhkannya?
node
npm
menginstal skrip sumber Node.js sebagai CLI (berpotensi tersedia secara global) , Anda harus menggunakan baris shebang - dannpm
bahkan akan membuatnya berfungsi di Windows; lihat jawaban saya yang sekali lagi diperbarui.Jawaban:
#!/usr/bin/env node
adalah contoh dari baris shebang : baris pertama dalam file teks biasa yang dapat dieksekusi pada platform mirip Unix yang memberi tahu sistem penerjemah apa yang harus meneruskan file itu untuk dieksekusi , melalui baris perintah setelah#!
awalan ajaib (disebut shebang ) .Catatan: Windows tidak tidak mendukung garis peristiwa , sehingga mereka secara efektif diabaikan ada; pada Windows itu hanya ekstensi nama file yang ditentukan yang menentukan apa yang dapat dieksekusi akan menafsirkannya. Namun, Anda tetap membutuhkannya dalam konteks
npm
. [1]Berikut ini, diskusi umum tentang garis shebang terbatas pada platform mirip Unix:
Dalam diskusi berikut saya akan berasumsi bahwa file yang berisi kode sumber untuk dieksekusi oleh Node.js hanya diberi nama
file
.Anda MEMBUTUHKAN baris ini , jika Anda ingin menjalankan file sumber Node.js secara langsung , sebagai file yang dapat dieksekusi dengan sendirinya - ini mengasumsikan bahwa file telah ditandai sebagai dapat dieksekusi dengan perintah seperti
chmod +x ./file
, yang kemudian memungkinkan Anda untuk memanggil file dengan, misalnya,,./file
atau, jika terletak di salah satu direktori yang terdaftar dalam$PATH
variabel, cukup sebagaifile
.npm
berdasarkan nilai"bin"
kunci dalampackage.json
file paket ; lihat juga jawaban ini untuk mengetahui cara kerjanya dengan paket yang diinstal secara global . Catatan kaki [1] menunjukkan bagaimana ini ditangani pada Windows.Anda TIDAK memerlukan baris ini untuk memanggil file secara eksplisit melalui
node
interpreter, misalnya,node ./file
Informasi latar belakang opsional :
#!/usr/bin/env <executableName>
adalah cara portable menentukan penerjemah: Singkatnya, ia mengatakan: mengeksekusi<executableName>
manapun Anda (pertama) menemukannya di antara direktori yang tercantum dalam$PATH
variabel (dan secara implisit lulus path ke file pada tangan).Ini menjelaskan fakta bahwa interpreter tertentu dapat diinstal di lokasi berbeda di seluruh platform, yang pasti terjadi
node
pada biner Node.js.Sebaliknya, lokasi
env
utilitas itu sendiri dapat diandalkan untuk berada di lokasi yang sama di seluruh platform, yaitu/usr/bin/env
- dan menentukan jalur lengkap ke dapat dieksekusi diperlukan dalam baris shebang.Perhatikan bahwa utilitas POSIX
env
sedang digunakan ulang di sini untuk mencari berdasarkan nama file dan menjalankan file yang dapat dieksekusi di file$PATH
.Tujuan sebenarnya dari
env
adalah untuk mengelola lingkungan untuk sebuah perintah - lihatenv
spesifikasi POSIX dan jawaban bermanfaat Keith Thompson .Perlu juga dicatat bahwa Node.js membuat pengecualian sintaks untuk baris shebang, karena baris tersebut bukan kode JavaScript yang valid (
#
bukan karakter komentar dalam JavaScript, tidak seperti di shell seperti POSIX dan interpreter lainnya).[1] Untuk kepentingan konsistensi lintas platform,
npm
membuat file pembungkus*.cmd
(file batch) di Windows saat menginstal file yang dapat dieksekusi yang ditentukan dalampackage.json
file paket (melalui"bin"
properti). Pada dasarnya, file batch pembungkus ini meniru fungsionalitas Shebang Unix: mereka memanggil file target secara eksplisit dengan eksekusi yang ditentukan di baris shebang - dengan demikian, skrip Anda harus menyertakan baris shebang bahkan jika Anda hanya bermaksud untuk menjalankannya di Windows - lihat jawaban ini milik saya untuk detailnya.Karena
*.cmd
file dapat dipanggil tanpa.cmd
ekstensi, ini membuat pengalaman lintas platform yang mulus: pada Windows dan Unix Anda dapat secara efektif menjalankannpm
CLI yang terinstal dengan nama aslinya, tanpa ekstensi.sumber
.cmd
dan.py
menentukan program apa yang akan digunakan untuk mengeksekusi file tersebut. Di Unix, garis shebang melakukan fungsi itu. Untuk membuatnpm
pekerjaan pada semua platform yang didukung, Anda memerlukan garis shebang bahkan di Windows.Skrip yang akan dieksekusi oleh penerjemah biasanya memiliki baris shebang di bagian atas untuk memberi tahu OS cara menjalankannya.
Jika Anda memiliki skrip bernama
foo
yang baris pertamanya adalah#!/bin/sh
, sistem akan membaca baris pertama itu dan menjalankan yang setara dengan/bin/sh foo
. Karena itu, sebagian besar penerjemah diatur untuk menerima nama file skrip sebagai argumen baris perintah.Nama juru bahasa setelah
#!
harus jalur lengkap; OS tidak akan mencari Anda$PATH
untuk menemukan juru bahasa.Jika Anda memiliki skrip untuk dieksekusi
node
, cara yang jelas untuk menulis baris pertama adalah:tetapi itu tidak berfungsi jika
node
perintah tidak diinstal di/usr/bin
.Sebuah solusi umum adalah dengan menggunakan
env
perintah (yang tidak benar-benar dimaksudkan untuk tujuan ini):Jika skrip Anda dipanggil
foo
, OS akan melakukan hal yang sama denganThe
env
perintah mengeksekusi perintah lain yang namanya diberikan pada baris perintah, melewati argumen berikut untuk perintah itu. Alasan digunakan di sini adalah untukenv
mencari$PATH
perintah. Jadi jikanode
dipasang di/usr/local/bin/node
, dan Anda memiliki/usr/local/bin
di Anda$PATH
, yangenv
perintah akan memanggil/usr/local/bin/node foo
.Tujuan utama dari
env
perintah ini adalah untuk menjalankan perintah lain dengan lingkungan yang dimodifikasi, menambahkan atau menghapus variabel lingkungan yang ditentukan sebelum menjalankan perintah. Tetapi tanpa argumen tambahan, itu hanya menjalankan perintah dengan lingkungan yang tidak berubah, yang Anda butuhkan dalam kasus ini.Ada beberapa kelemahan dari pendekatan ini. Sebagian besar sistem mirip Unix modern memilikinya
/usr/bin/env
, tetapi saya bekerja pada sistem yang lebih lama tempatenv
perintah dipasang di direktori yang berbeda. Mungkin ada batasan pada argumen tambahan yang dapat Anda berikan menggunakan mekanisme ini. Jika pengguna tidak memiliki direktori yang berisinode
perintah di$PATH
, atau memiliki beberapa perintah berbeda yang dipanggilnode
, maka ia dapat menjalankan perintah yang salah atau tidak berfungsi sama sekali.Pendekatan lainnya adalah:
#!
garis yang menentukan jalur lengkap kenode
perintah itu sendiri, memperbarui skrip sesuai kebutuhan untuk sistem yang berbeda; ataunode
perintah dengan skrip Anda sebagai argumen.Lihat juga pertanyaan ini (dan jawaban saya ) untuk diskusi lebih lanjut tentang
#!/usr/bin/env
triknya.Kebetulan, di sistem saya (Linux Mint 17.2), itu diinstal sebagai
/usr/bin/nodejs
. Menurut catatan saya, itu berubah dari/usr/bin/node
ke/usr/bin/nodejs
antara Ubuntu 12.04 dan 12.10. The#!/usr/bin/env
trick tidak akan membantu dengan itu (kecuali jika Anda menyiapkan symlink atau yang serupa).UPDATE: Komentar oleh mtraceur mengatakan (diformat ulang):
Saya belum pernah menggunakan NodeJS belakangan ini. Harapan saya adalah bahwa masalah
nodejs
vs.node
telah diselesaikan selama bertahun-tahun sejak saya pertama kali memposting jawaban ini. Di Ubuntu 18.04,nodejs
paket diinstal/usr/bin/nodejs
sebagai symlink ke/usr/bin/node
. Pada beberapa OS sebelumnya (Ubuntu atau Linux Mint, saya tidak yakin yang mana), adanodejs-legacy
paket yang disediakannode
sebagai symlinknodejs
. Tidak ada jaminan bahwa saya memiliki semua detail dengan benar.sumber
nodejs
vsnode
adalah memulai file dengan enam baris berikut: 1)#!/bin/sh -
, 2)':' /*-
3)test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
4)test2=$(node --version 2>&1) && exec node "$0" "$@"
, 5)exec printf '%s\n' "$test1" "$test2" 1>&2
6)*/
. Ini pertama-tama akan mencobanodejs
dan kemudian mencobanode
, dan hanya mencetak pesan kesalahan jika keduanya tidak ditemukan. Penjelasan berada di luar cakupan komentar ini, saya hanya meninggalkannya di sini jika itu membantu siapa pun mengatasi masalah karena jawaban ini memunculkan masalah.-
pada#!
baris?-
dalam#!/bin/sh -
hanyalah sebuah kebiasaan yang membuat yakin berperilaku shell tepat di sangat sempit dan tidak mungkin set keadaan yang nama script atau path relatif bahwa shell melihat dimulai dengan-
. (Juga, ya, sepertinya setiap distro utama telah berkumpul kembalinode
sebagai nama utama. Saya tidak menggali untuk memeriksa ketika membuat komentar saya, tetapi sejauh yang saya tahu hanya pohon keluarga distro Debian yang digunakannodejs
, dan sepertinya seperti mereka semua kembali ke dukungannode
saat Debian melakukannya.)-x
dan-v
", tetapi sejak awal suka Bourne hanya mengurai argumen pertama sebagai opsi yang memungkinkan, dan karena shell dimulai dengan opsi tersebut dimatikan , menyebabkan shell tidak mencoba mengurai nama skrip sejak aslinya, dan tetap dapat disalahgunakan karena perilaku tersebut dipertahankan di Bourne-like modern untuk alasan kompatibilitas. Jika saya ingat semua sejarah Bourne dan trivia portabilitas saya, benar.Jawaban singkat: Ini adalah jalan menuju penerjemah.
EDIT (Long Answer): Alasan tidak ada garis miring sebelum "node" adalah karena Anda tidak selalu dapat menjamin keandalan #! / Bin /. Bit "/ env" membuat program menjadi lebih lintas platform dengan menjalankan skrip di lingkungan yang dimodifikasi dan lebih andal karena dapat menemukan program interpreter.
Anda belum tentu membutuhkannya, tetapi bagus digunakan untuk memastikan portabilitas (dan profesionalisme)
sumber
/usr/bin/env
bit tidak memodifikasi lingkungan. Itu hanya sebuah perintah di lokasi (kebanyakan) yang diketahui yang memanggil perintah lain yang diberikan sebagai argumen, dan mencari$PATH
untuk menemukannya. Intinya adalah bahwa#!
baris tersebut membutuhkan jalur lengkap ke perintah yang dipanggil, dan Anda tidak perlu tahu di mananode
diinstal.