Universal Node.js Instagram Hesabındaki Resim ve Videoları shebang


42

Node.js bu günlerde çok popüler ve üzerine bazı senaryolar yazıyorum. Ne yazık ki, uyumluluk bir sorundur. Resmi olarak, Node.js yorumlayıcısının aranması gerekiyordu node, ancak Debian ve Ubuntu nodejsbunun yerine bir çalıştırılabilir dosya gönderiyor.

Node.js'in olabildiğince çok durumda çalışabileceği taşınabilir komut dosyaları istiyorum. Dosya adının olduğu varsayımıyla, foo.jsgerçekten komut dosyasının iki şekilde çalışmasını istiyorum:

  1. ./foo.jsSenaryoyu çalıştırırsa ya nodeya nodejsiçindedir $PATH.
  2. node foo.jsAyrıca betiği çalıştırır (tercümanın çağrıldığı varsayılarak node)

Not: xavierm02 ve kendimin cevapları bir polyglot betiğinin iki çeşididir. Eğer varsa, hala saf bir Shebang çözümüyle ilgileniyorum.


Bunun gerçek bir çözüm olmadığını düşünüyorum, çünkü yapının çalıştırma sistemleri tarafından keyfi olarak adlandırılmasına izin veriliyor. Seni python yorumlayıcısı alphacentauri olarak adlandırmaktan alıkoyan hiçbir şey yok, sadece kuralları takip edip adını python olarak adlandırıyorsun. nodeSenaryonuz için standart bir isim kullanmanızı veya shebang'ı değiştiren bir tür kod yazmanızı öneririm .

@ G.Kayaalp Politika ve sözleşmeler bir yana, bir çok Debian / Ubuntu / Fedora kullanıcısı var ve onlar için çalışan senaryolar oluşturmak istiyorum. Bunun için bir derleme sistemi kurmak istemiyorum (kim çalıştırmadan önce kabuk komut dosyaları oluşturur?), Ne de desteklemek istemiyorum alphacentauri. Adı verilen bir çalıştırılabilir dosya nodejsvarsa, Node.js. olduğundan% 99 emin olabilirsiniz. Neden ikisini de destekler nodejsve node?
dancek,

Nodejs-legacy paketini kurun. Buna ihtiyaç duyulmasının nedeni, ismin çok kibirli bir şekilde jenerik olması, önce başka birinin adını almasıdır. Ancak, diğer paket adı paylaşmaya istekliydi.
user3710044

Yanıtlar:


54

Karşılaştığım en iyisi, gerçekten bir polyglot (Bourne kabuğu / Node.js) betiği olan bu "iki satırlık shebang" dır:

#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"

console.log('Hello world!');

İlk satır, belli ki, bir Bourne kabuğu shebang. Node.js, bulduğu herhangi bir shebang'ı atlar, bu nedenle Node.js için geçerli bir javascript dosyasıdır.

İkinci satır, kabuk işlemsize aramaları :bağımsız değişken ile //çalıştırır ve daha sonra nodejsya da nodebir parametre olarak bu dosya adıyla. taşınabilirlik command -vyerine kullanılır which. Komut değiştirme sözdizimi $(...)kesinlikle Bourne değil, bu yüzden 1980'lerde çalıştırırsanız backticks'i tercih edin.

Node.js sadece ':'no-op benzeri bir dize değerlendirir ve satırın geri kalanı yorum olarak ayrıştırılır.

Dosyanın geri kalanı sadece düz eski javascript. Alt kabuk exec, ikinci satırın tamamlanmasından sonra sona erer , bu nedenle dosyanın geri kalanı asla kabuk tarafından okunmaz.

İlham için xavierm02 ve ek bilgi için tüm yorumculara teşekkürler!


1
Harika çözüm ':'Yaklaşımın bir alternatifi kullanmaktır // 2>/dev/null(ki ne nvmişe yarar ): bash yapmak, bash: //: Is a directoryyönlendirmenin 2>/dev/nullsessizce görmezden geldiği bir hatadır ( ) ; JavaScript’te tüm satır bir yorum haline gelir. Ayrıca - ve bunun bir problem olmasını beklemiyorum IRL - commandkabuk fonksiyonlarını ve takma adlarını da rapor ettiği bir tuhaflığa sahiptir -v- aslında onları çağırmaz. Dışa kabuk işlevlerini ve hatta takma adları (varsayarak sahip olur Böylece shopt -s expand_aliases) adında nodeveya nodejsişler kırılabilir.
mklement0

1
Pekala, POSIX sh bugünlerde çok yaygın (Solaris / bin / sh hariç - ancak Solaris, POSIX uyumlu olan kutudan AT&T ksh ile geliyor) ve Markus Kuhn'un (haklı olarak) kapalı kalmasını tavsiye ediyor. IMHO asla ihtiyacın olmaz. Ama evet, yeter mksh, bash, dashçağdaş Unix ve GNU sistemlerinde ve diğer kabuklar.
mirabilos

1
Mükemmel çözüm; daha çok taşınabilir kullanmak #!/usr/bin/env shyerine kullanmak #!/bin/sh( en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability için ) olsa da
user7089

2
#!/usr/bin/env sh"Daha taşınabilir" olarak reklam vermeye dikkat ederdim . Aynı Wikipedia makalesi, "Bu çoğunlukla işe yarıyor / usr / bin / env yolu env yardımcı programı için kullanılıyor ..." diyor. Bu harika bir onay değil ve benim tahminim, /usr/bin/envdaha sık olmadan sistemlere gireceğinizdir. Eğer /bin/shsıklıkta herhangi bir farklılık varsa, sistemler olmadan çalışırsınız.
sheldonh

1
@ dancek 2018'den Merhaba //bin/sh -c :; exec ..., ikinci hattın daha temiz bir versiyonu olmaz mıydı ?
har-wradim

10
#!/bin/sh
//bin/false || `which node || which nodejs` << `tail -n +2 $0`
console.log('ok');

//bin/false/bin/falseİkinci eğik çizginin düğümü yorumuna dönüştürmesi dışında olduğu gibi , ve bu yüzden burada. Ardından, ilk tarafın sağ tarafı ||değerlendirilir. 'which node || which nodejs'tırnak yerine tırnak işaretleri ile düğümü başlatır ve <<sağdaki her şeyi besler. //Dancek ile başlayan bir sınırlayıcıyı kullanabilirdim, işe yarayacaktı ama başlangıçta sadece iki satır olmasını daha temiz buldum, böylece tail -n +2 $0dosyanın ilk iki satır dışında kendisini okumasını isterdim .

Düğümde çalıştırırsanız, ilk satır bir shebang olarak tanınır ve yok sayılır ve ikincisi bir satırlık bir yorumdur.

(Görünüşe göre, sed ilk ve son satırlar olmadan kuyruk Yazdırma dosyası içeriğini değiştirmek için kullanılabilir )


Düzenlemeden önce cevapla:

#!/bin/sh
`which node || which nodejs` <<__HERE__
console.log('ok');
__HERE__

Ne istersen yapamazsın, yani ne yaparsan yap bir kabuk betiği çalıştır, yani #!/bin/sh. Bu kabuk betiği, düğümü yürütmek için gereken dosyanın yolunu alır which node || which nodejs. Ters 'which node || which nodejs'tırnaklar burada yürütülür, böylece (tırnak işaretleri yerine ters tırnak işaretleriyle) sadece düğümü çağırır. Sonra sen sadece senaryoyu onunla besle <<. __HERE__Senin script sınırlayıcı bulunmaktadır. Ve bu console.log('ok');, senaryonuzla değiştirmeniz gereken bir script örneğidir.


bir açıklama güzel olurdu
0xC0000022L

Daha iyi çalıştırılmadan önce JavaScript kodu üzerinde yapılacak önlemek parametre genişletme, komut ikamesi ve aritmetik genişleme için buraya-belge ayırıcı alıntı: <<'__HERE__'.
Manatwork

Bu ilginçleşiyor! Her ne kadar //bin/falseMSYS ortamımda çalışmıyorsa ve nodebulunduğum yerde backticks'in etrafında alıntılara ihtiyacım var C:\Program Files\.... Evet, korkunç bir ortamda çalışıyorum ...
dancek

1
//bin/falseMac OS X'te de çalışmıyor. Üzgünüm, ama bu artık pek taşınabilir görünmüyor.
dancek,

2
whichKomut ayrıca taşınabilir değildir.
jordanm

9

Bu, yalnızca politikanın gereğinden fazla anlaşıldığı Debian tabanlı sistemlerde bir sorundur.

Fedora'nın nodejs denilen bir ikili dosyası ne zaman sağladığını bilmiyorum, ama hiç görmedim. Paket düğüm olarak adlandırılır ve düğüm olarak adlandırılan bir ikili dosya yükler.

Sadece Debian tabanlı sistemlerinize sağduyulu uygulamak için bir link kullanın ve daha sonra aklı başında bir shebang kullanabilirsiniz. Diğer insanlar zaten aklı başında shebangs kullanacaklar, o yüzden bu bağlantıya ihtiyacınız olacak.

#!/usr/bin/env node

console.log("Spread the love.");

Üzgünüm, ama bu soruyu cevaplamıyor. Siyasi bakış açısını anlıyorum ama buradaki mesele bu değil.
dancek,

Kayıt için, bazı Fedora sistemlerinde nodejsçalıştırılabilir bir dosya var , ancak bu Fedora'nın hatası değil. Gerçeği yanlış bildirdiğim için üzgünüm.
dancek, 05

8
Özüre gerek yok. Oldukça haklısın. Cevabım, sorunuza cevap vermiyor. Sorunuzla konuşur, sorunun kapsamı mevcut olandan daha az kullanışlı çözümlerle sınırlar. Tarih tarafından bilgilendirilen pratik tavsiyeler veriyorum. Düğüm, burada kendini bulan ilk tercüman değil. Larry Wall'in PERLang'ın olması gerektiğini beyan ettiğini gösteren kargaşayı görmeliydin #!/usr/bin/perl. Bununla birlikte, önerilerimi beğenmek veya uygulamak zorunda değilsiniz. Barış.
sheldonh

3

Küçük bir .shdosya oluşturmayı sakıncası yoksa, sizin için küçük bir çözümüm var. Hangi düğümü kullanabileceğini belirlemek için küçük bir kabuk betiği oluşturabilir ve bu betiği shebang'ınızda kullanabilirsiniz:

shebang.sh :

#!/bin/sh
`which node || which nodejs` $@

script.js :

#!./shebang.sh
console.log('hello');

Her ikisini de çalıştırılabilir olarak işaretleyin ve çalıştırın ./script.js.

Bu şekilde, polyglot komut dosyası kullanmaktan kaçının. İyi bir fikir gibi görünse de, birden fazla shebang hattı kullanmanın mümkün olduğunu sanmıyorum.

Bu, sorunu istediğiniz gibi çözmesine rağmen, hiç kimsenin bunu umursamadığı anlaşılıyor. Örneğin, uglifyjs ve coffeescript kullanır #!/usr/bin/env node, npm giriş noktası olarak bir kabuk betiği kullanır ve yine açıkça adı ile yürütülebilir dosyayı çağıran bir komut dosyası kullanır node. Ben bir Ubuntu kullanıcısıyım ve bunu her zaman düğümü derlerken bilmiyordum. Bunu bir hata olarak rapor etmeyi düşünüyorum.


En azından kullanıcıdan chmod +xsh betiğinde sormasını istemeniz gerektiğinden eminim ... bu yüzden onlardan çalıştırılabilir düğümlerine konum veren bir değişken ayarlamalarını isteyebilirsiniz ...
xavierm02

@ xavierm02 chmod +x'd. Ve bir NODE değişkeninin daha iyi olduğuna katılıyorum which node || which nodejs. Ancak, birçok önemli düğüm projesi yalnızca kullanmasına rağmen, araştırıcı kullanıma hazır bir deneyim sunmak istiyor #!/usr/bin/env node.

1

Sadece burada tam olması için ikinci satırı yapmanın birkaç yolu var:

// 2>/dev/null || echo yes
false //|| echo yes

Ancak, seçilen yanıttan hiçbir avantajı yoktur:

':' //; || echo yes

Ayrıca, ya nodeda nodejsher ikisinin de bulunacağını biliyorsanız , aşağıdakiler işe yarar :

exec `command -v node nodejs` "$0" "$@"

Ama bu büyük bir "eğer", bu yüzden seçilen cevabın en iyisi olduğunu düşünüyorum.


Ek foobar // 2>/dev/nullolarak foobar, herhangi bir komut olmadığı sürece herhangi bir şeyi çalıştırabilirsiniz . Ve herhangi bir POSIX sisteminde bulunan yardımcı programların çoğu //argümanla çalıştırılabilir .
dancek,

1

Bunun soruyu cevaplamadığını anlıyorum, ancak sorunun yanlış bir öncülle sorulduğuna inanıyorum.

Ubuntu burada yanlış. Kendi senaryonuz için evrensel bir shebang yazmak, de-facto standardını kullanan, üzerinde hiçbir kontrolünüz olmayan diğer paketleri değiştirmeyecektir #!/usr/bin/env node. Sisteminiz gerekir sağlamak nodeiçinde PATHo çalıştırmak için nodejs hedefleyen herhangi komut dosyaları için isterse.

Örneğin, Ubuntu tarafından sağlanan npmpaket bile, shebang'ları paketlere yeniden yazmaz:

$ cd
$ rm -rf test_npm
$ mkdir test_npm
$ cd test_npm
$ npm install mkdirp 2>&1 | grep -ve home
`-- mkdirp@0.5.1
  `-- minimist@0.0.8

npm WARN test_npm No description
npm WARN test_npm No repository field.
npm WARN test_npm No README data
npm WARN test_npm No license field.
$ node_modules/.bin/mkdirp testdir
/usr/bin/env: 'node': No such file or directory
$ head -n1 node_modules/.bin/mkdirp
#!/usr/bin/env node
$ npm --version
3.5.2
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.