Shebang satırına göre bir script çalıştırmak için bir komut var mı?


46

Yürütme izni ayarlanmamış bir bash betiği çalıştırmak istersem, yapabilirim:

bash script.sh

Ne yerine kullanması gereken bashkomut değil çalıştırılabilir ise ve ben doğru tercüman bilmiyor musunuz? Tercümanı shebang hattından arayan ve betiğini de uygulayan bir komut var mı?


Yanlış olan ne?
steffen

@ steffen Söz konusu dosyanın bir bash betiği olduğunu nereden biliyorsunuz?
muru

@muru'dan alıntı: "Eğer bir bash betiği çalıştırmak istersem ..." Üstelik (bash betiği olmasa bile), eğer bash whateverçalışıyorsa, neden farklı bir şey kullanmalısın? bash hemen hemen her * ix sisteminde mevcuttur, peki neden rahatsız etmeyin ...
steffen

1
@steffen sorunun geri kalanını okudunuz mu? Dediler ki: "Eğer ... o zaman yapabilirim: ..." ve "Eğer doğru tercümanı bilmiyorsam, bash yerine ne kullanmalıyım ?"
muru

@muru: belki de açıkça göremiyorum. Fakat eğer dosyada / shebang satırı varsa, soruda belirtildiği gibi, bash tam olarak isteneni yapacaktır. Perl gibi, aşağıdaki cevaba göre. Peki bash kullanmamanın avantajı nedir?
steffen

Yanıtlar:


67

Evet. Denir perl:

perl foo.bash    # works
perl foo.lua     # works
perl foo.clisp   # works
perl foo.csh     # works
perl foo.php     # works
perl foo.gnuplot # works (no arguments)
perl foo.pl      # works (obviously)
perl foo.py      # works
perl foo.sh      # works
perl foo.tcl     # works
perl foo.rb      # works
perl foo.nodejs  # works
perl foo.r       # works
perl foo.oct     # works
perl foo.csharp  # works (no arguments)

Perl'in belgelerinde bahsedilmiştir :

Eğer #!hat kelime "perl" ne de kelime "indir" isminin verildiği programa içermiyor #!yerine Perl tercüman yürütülür. Bu biraz tuhaf, ama yapmayan makinelerde insanlara yardımcı oluyor #!, çünkü bir programa SHELL'lerinin / usr / bin / perl olduğunu söyleyebilirler ve Perl daha sonra programı kendileri için doğru tercümana gönderir.


40
Şey, bu sadece kirli.
İnce

1
Dosya uzantısı .jsda çalışıyor mu?
Kasım’da Pysis

1
Ayrıca, makineler ne yapmaz #!. Şimdi birkaç tane daha var gibi görünüyorum ve bu sorunu yaşamamış oldum.
Kasım’da Pysis

1
Tamam, bu sadece sizin örneğiniz , dosyalardan birkaç shebang satırı sergilemek yerine, çok sayıda dosya uzantısını vurgulamak gibiydi ve tahmininin nasıl çalıştığını sanıyorum.
Pysis

2
Ne kadar man perlrunutanç verici bir şekilde "biraz tuhaf" olduğunu kabul etmekten hoşlanırım :). Bunun UNIX dışı ortamlara ve UNIX'in çok eski sürümlerine yönelik bir merak olarak görülmesi gerektiğini düşünüyorum .
İnce

25

Scriptler mutlaka bir shebang yok

Komut yorumlayıcı çalıştırılabilir ise, Bunu shebang sahip olduğundan emin olamaz hiç . Tercüman çalıştırmak komut dosyaları, shebang gerekmez , eğer sen kod çalıştırmasına tercüman diyoruz.

Bu nedenle cevap hayır, komut dosyasının çalışacağı dilin (tercüman) ne olduğundan emin olacak bir komut yok. Bununla birlikte, her zaman senaryo içine bakabilir ve öğrenmek için shebang olup olmadığını görebilirsiniz.

Kısacası kurallar:

  1. Senaryoyu çalıştırdığınızda, tercümanı çağırmak, her zaman çalıştırılabilir olsun ya da olmasın, olası shebang'ları geçersiz kılar.
  2. Çalıştırılabilir ve çalıştırın Değilse gelen tercüman, script hiçbir shebang ihtiyacı var.
  3. Komut ilk tercüman uğramadan çalıştırılırsa, bu ihtiyacı (ve kullanımları) shebang neyi çağrısına tercüman bulmak için, ve onun shebang gelen tercüman çağırmak için "iznine" sahip olmak yürütülebilir olması gerekiyor.

Eğer senaryoda shebang yoksa, hangi tercümanın kullanılacağını söylemek için script içinde hiçbir doğrudan bilgi yoktur.

Bunu söyledikten

Elbette, her zaman kodun shebang olup olmadığını bulmaya çalışmak için bir sarmalayıcı komut dosyası yazabilir ve yorumlayıcıyı bundan okuyabilir, ardından bulunan tercümandan çalıştırabilirsiniz.

Bir örnek

#!/usr/bin/env python3
import subprocess
import sys

args = sys.argv[1:]; script = args[0]

try:
    lang = open(script).readlines()[0].replace("#!", "").strip().split()[-1]
    cmd = [lang, script]+args[1:]
    subprocess.call(cmd)
except (PermissionError, FileNotFoundError, IndexError):
    print("No valid shebang found")
  • Bunun kaydet tryruniçinde $PATH(mesela ~/binbunu yapmak, bu mevcut, çıkış yapıp geri vermezse, dizin olun) çalıştırılabilir . Sonra çalışıyor:

    tryrun /path/to/nonexecutablescript

    çalıştırılamaz pythonve bashkomut dosyalarımdaki doğru tercümanı arar (test eder) .

açıklama

  • Betik sadece betiğin ilk satırını okur, kaldırır #!ve yorumlayıcıyı çağırmak için gerisini kullanır.
  • Geçerli bir tercüman arayamazsa, a PermissionErrorveya a değerini yükseltir FileNotFoundError.

Not

Uzantı ( .sh, .pyetc), Linux'taki uygun tercümanı belirlemede hiçbir rol oynamaz.


(* Elbette koddan sözdizimini belirlemek için "akıllı" bir tahmin algoritması geliştirmek mümkündür.)


Tamam, bu Linux'un bir yerde uyguladığı shebang çıkarma işlemine rağmen (çalıştırılabilir srcipts için doğru yorumlayıcıyı seçebilmesi için), bağımsız bir standart komut olarak sağlanmadığı anlamına gelir.
Aivar

Shebang ayık @Aivar sorun değil, ancak kod olmadan onsuz çalışan mükemmel.
Jacob Vlijm

@Aivar Ah, ne demek istediğini anlıyorum. Komut dosyası çalıştırılabilirse ve komutta dil olmadan çalıştırılıyorsa, komut dosyası çevreyi değil, yorumlayıcıyı çağırır.
Jacob Vlijm

1
@JacobVlijm "betiği tercümanı çağırıyor" demiyorum, daha çok "Linux çekirdeği betiği çalıştırırken hangi tercümanın arayacağını bulmak için".
Paŭlo Ebermann 17:16

@ PaŭloEbermann Teşekkürler! Tabii ki doğru. Çekirdek tüm prosedürü her iki şekilde de halleder, ancak mecazi olarak ve bence daha iyi anladığına göre, senaryonun hangi tercümanın çağırılacağına (ve gerçekte yapması) dikkat etmesine "izin verildiğini" söylemek olduğunu düşünüyorum. İfadelerden emin değilim, ancak çekirdeği aslında işi yaparken girişimin senaryodaki gibi tanımlamak istiyorum.
Jacob Vlijm 17:16

6

Bunu, böyle bir komut dosyasıyla başarabilirsiniz:

#!/bin/bash

copy=/tmp/runner.$$
cp $1 ${copy}
chmod u+x ${copy}
${copy}
rm ${copy}

Böylece:

$ echo "echo hello" > myscript
$ ./myscript
bash: ./myscript: Permission denied
$ ./runscript myscript 
hello

Bunu yapmamayı tavsiye ederim. İzinlerin bir nedeni var. Bu, izinlerin düşürülmesi için bir programdır.

Shebang işleminin bir çekirdek işlevi olduğunu unutmayın (Linux kaynak kodunda - fs/binfmt_script.c). Temel olarak, doğrudan bir betiği çağıran süreç hakkında bir şey bilmiyor #!- çekirdek, bir tercüman başlatması gerektiğini anlamak için kullanır.


2
Bunun her zaman kabuğun bir işlevi olduğunu varsayıyordum, çekirdeği değil. Bugün yeni bir şey öğrendim.
kayıkçı

1
@boatcoder - İlgilendiğiniz için, Linux kaynak kodunun işlediği yere bir bağlantı ekleyin.
İnce
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.