Node.js sangat populer hari ini dan saya telah menulis beberapa skrip di atasnya. Sayangnya, kompatibilitas adalah masalah. Secara resmi, interpreter Node.js seharusnya dipanggil node
, tetapi Debian dan Ubuntu mengirim eksekutabel yang dipanggil nodejs
.
Saya ingin skrip portabel yang dapat digunakan Node.js dalam situasi sebanyak mungkin. Dengan asumsi nama file adalah foo.js
, saya benar-benar ingin skrip berjalan dalam dua cara:
./foo.js
menjalankan skrip jika adanode
ataunodejs
ada di$PATH
.node foo.js
juga menjalankan skrip (dengan asumsi penerjemah disebutnode
)
Catatan: Jawaban oleh xavierm02 dan saya sendiri adalah dua variasi skrip polyglot. Saya masih tertarik dengan solusi shebang murni, jika ada.
scripting
compatibility
node.js
dancek
sumber
sumber
node
untuk skrip Anda, atau memiliki semacam skrip make yang memodifikasi shebang.alphacentauri
dan semacamnya. Jika ada executable yang dipanggilnodejs
, Anda bisa 99% yakin itu Node.js. Mengapa tidak mendukung keduanyanodejs
dannode
?Jawaban:
Yang terbaik yang saya hasilkan adalah skrip "dua baris" yang benar-benar adalah skrip polyglot (Bourne shell / Node.js):
Baris pertama adalah, jelas, shell Bourne shebang. Node.js memintas setiap shebang yang ditemukannya, jadi ini adalah file javascript yang valid sejauh menyangkut Node.js.
Baris kedua memanggil no-op shell
:
dengan argumen//
dan kemudian mengeksekusinodejs
ataunode
dengan nama file ini sebagai parameter.command -v
digunakan bukanwhich
untuk portabilitas. Sintaks substitusi perintah$(...)
tidak sepenuhnya Bourne, jadi pilihlah backticks jika Anda menjalankan ini pada 1980-an.Node.js hanya mengevaluasi string
':'
, yang seperti no-op, dan sisa baris diuraikan sebagai komentar.Sisa file hanyalah javascript lama. Subshell berhenti setelah
exec
baris kedua selesai, sehingga sisa file tidak pernah dibaca oleh shell.Terima kasih kepada xavierm02 untuk inspirasi dan semua komentator untuk informasi tambahan!
sumber
':'
pendekatan ini adalah dengan menggunakan// 2>/dev/null
(yangnvm
artinya): untuk mem-bash, ini adalah kesalahan (bash: //: Is a directory
), yang diabaikan oleh pengalihan2>/dev/null
; ke JavaScript, seluruh baris menjadi komentar. Juga - dan saya tidak berharap ini menjadi masalah IRL -command
memiliki kekhasan di mana ia juga melaporkan fungsi dan alias shell-v
- meskipun itu tidak benar-benar memanggil mereka. Dengan demikian, jika Anda telah mengekspor fungsi shell atau bahkan alias (dengan asumsishopt -s expand_aliases
) bernamanode
ataunodejs
, semuanya dapat rusak.mksh
,bash
,dash
dan kerang lainnya di zaman modern Unix dan GNU sistem.#!/usr/bin/env sh
alih-alih#!/bin/sh
(per en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability )#!/usr/bin/env sh
sebagai "lebih portabel". Artikel Wikipedia yang sama mengatakan, "Ini sebagian besar bekerja karena path / usr / bin / env umumnya digunakan untuk utilitas env ..." Itu bukan dukungan yang luar biasa, dan tebakan saya adalah bahwa Anda akan menjalankan sistem tanpa/usr/bin/env
lebih sering daripada Anda mengalami sistem tanpa/bin/sh
, jika ada perbedaan frekuensi sama sekali.//bin/sh -c :; exec ...
versi yang lebih bersih dari baris kedua?//bin/false
adalah hal yang sama dengan/bin/false
kecuali bahwa garis miring kedua mengubahnya menjadi komentar untuk simpul, dan itulah sebabnya ada di sini. Kemudian, sisi kanan yang pertama||
dievaluasi.'which node || which nodejs'
dengan backquotes alih-alih tanda kutip meluncurkan node dan<<
feed itu apa pun yang ada di sebelah kanan. Saya bisa menggunakan pembatas dimulai dengan//
seperti dancek lakukan, itu akan berhasil tetapi saya merasa lebih bersih untuk memiliki hanya dua baris di awal jadi saya dulutail -n +2 $0
membuat file membaca sendiri kecuali dua baris pertama.Dan jika Anda menjalankannya dalam simpul, baris pertama dikenali sebagai shebang dan diabaikan dan yang kedua adalah komentar satu baris.
(Rupanya, sed dapat digunakan untuk mengganti konten file Cetak ekor tanpa baris pertama dan terakhir )
Jawab sebelum edit:
Anda tidak dapat melakukan apa yang Anda inginkan sehingga yang Anda lakukan adalah menjalankan skrip shell, karenanya
#!/bin/sh
. Script shell itu akan mendapatkan path file yang diperlukan untuk mengeksekusi node, yaituwhich node || which nodejs
. Backquotes ada di sini sehingga dieksekusi, jadi'which node || which nodejs'
(dengan backquotes bukan tanda kutip) cukup memanggil node. Kemudian, Anda cukup memberi makan skrip Anda dengannya<<
. The__HERE__
adalah pembatas script Anda. Danconsole.log('ok');
ini adalah contoh skrip yang harus Anda ganti dengan skrip Anda.sumber
<<'__HERE__'
.//bin/false
tidak berfungsi di lingkungan MSYS saya, dan saya perlu tanda kutip di sekitar backticks ketika sayanode
berada diC:\Program Files\...
. Ya, saya bekerja di lingkungan yang mengerikan ...//bin/false
juga tidak berfungsi di Mac OS X. Maaf, tapi ini sepertinya tidak lagi portabel.which
perintah juga tidak portabel.Ini hanya masalah pada sistem berbasis Debian, di mana kebijakan mengatasi akal sehat.
Saya tidak tahu kapan Fedora menyediakan biner yang disebut nodejs, tapi saya tidak pernah melihatnya. Paket ini disebut nodejs dan menginstal biner yang disebut simpul.
Cukup gunakan symlink untuk menerapkan akal sehat ke sistem berbasis Debian Anda, dan kemudian Anda dapat menggunakan shebang yang waras. Orang lain akan menggunakan shebang waras, jadi Anda akan memerlukan symlink itu.
sumber
nodejs
executable , tetapi itu bukan kesalahan Fedora. Maaf telah salah menggambarkan fakta.#!/usr/bin/perl
. Karena itu, Anda tidak wajib menyukai atau menerapkan saran saya. Perdamaian.Jika Anda tidak keberatan membuat
.sh
file kecil , saya punya sedikit solusi untuk Anda. Anda bisa membuat skrip shell kecil untuk menentukan simpul mana yang dapat dieksekusi untuk digunakan, dan menggunakan skrip ini di shebang Anda:shebang.sh :
script.js :
Tandai keduanya executable, dan jalankan
./script.js
.Dengan cara ini, Anda menghindari skrip polyglot. Saya tidak berpikir menggunakan beberapa garis shebang mungkin dilakukan, meskipun sepertinya ide yang bagus.
Meskipun ini menyelesaikan masalah seperti yang Anda inginkan, tampaknya tidak ada yang peduli tentang ini. Misalnya, uglifyjs dan CoffeeScript penggunaan
#!/usr/bin/env node
, NPM menggunakan script shell sebagai pintu masuk, yang lagi-lagi menyebut dieksekusi secara eksplisit dengan namanode
. Saya adalah pengguna Ubuntu, dan saya tidak tahu ini karena saya selalu mengkompilasi simpul. Saya sedang mempertimbangkan untuk melaporkan ini sebagai bug.sumber
chmod +x
menggunakan skrip sh ... jadi Anda mungkin juga meminta mereka untuk menetapkan variabel yang memberikan lokasi ke node yang dapat dieksekusi ...chmod +x
'd. Dan saya setuju bahwa variabel NODE lebih baik daripadawhich node || which nodejs
. Tetapi penanya ingin memberikan pengalaman out-of-the-box, meskipun banyak proyek simpul utama hanya menggunakan#!/usr/bin/env node
.Hanya untuk melengkapi, berikut adalah beberapa cara lain untuk melakukan baris kedua:
Tetapi tidak ada yang memiliki keunggulan atas jawaban yang dipilih:
Juga, jika Anda tahu bahwa salah satu
node
ataunodejs
(tetapi tidak keduanya) akan ditemukan, berikut ini berfungsi:Tapi itu "jika" besar, jadi saya pikir jawaban yang dipilih tetap yang terbaik.
sumber
foobar // 2>/dev/null
selamafoobar
bukan perintah. Dan banyak utilitas yang ditemukan pada sistem POSIX dapat dijalankan dengan//
argumen.Saya mengerti bahwa ini tidak menjawab pertanyaan, tetapi saya yakin bahwa pertanyaan itu diajukan dengan premis yang salah.
Ubuntu salah di sini. Menulis universal shebang untuk skrip Anda sendiri tidak akan mengubah paket lain yang tidak dapat Anda kendalikan yang menggunakan standar de-facto
#!/usr/bin/env node
. Sistem Anda harus memberikannode
diPATH
jika ingin untuk script menargetkan nodejs untuk berjalan di atasnya.Misalnya, bahkan
npm
paket yang disediakan Ubuntu tidak menulis ulang paket dalam paket:sumber