มีคำสั่งสำหรับเรียกใช้สคริปต์ตามบรรทัดของ shebang หรือไม่


46

หากฉันต้องการรันสคริปต์ทุบตีที่ไม่มีชุดสิทธิ์ดำเนินการฉันสามารถทำได้:

bash script.sh

ฉันควรใช้อะไรbashหากสคริปต์ไม่สามารถใช้งานได้และฉันไม่รู้จักล่ามที่ถูกต้อง มีคำสั่งที่ค้นหาล่ามจากแถว shebang และรันสคริปต์ด้วยหรือไม่


มีอะไรผิดปกติทุบตี?
steffen

@steffen คุณจะรู้ได้อย่างไรว่าไฟล์นั้นเป็นสคริปต์ทุบตี
muru

@muru อ้างจากคำถาม: "ถ้าฉันต้องการรันสคริปต์ทุบตี ... " ยิ่งไปกว่านั้น (แม้ว่าจะไม่ใช่สคริปต์ทุบตี) หากใช้bash whateverงานทำไมต้องใช้อะไรที่แตกต่างกัน? ทุบตีมีอยู่ในแทบทุกระบบ ix * ดังนั้นทำไมรำคาญ ...
Steffen

1
@steffen คุณอ่านส่วนที่เหลือของคำถามหรือไม่ พวกเขาพูดว่า: "ถ้า ... ถ้าอย่างนั้นฉันสามารถทำได้: ... " และ "ฉันควรใช้อะไรแทนที่จะทุบตีถ้า ... ฉันไม่รู้ล่ามที่ถูกต้อง "
muru

@muru: บางทีฉันไม่เห็นชัดเจน แต่ถ้าไฟล์ / มี / shebang บรรทัดตามที่ระบุไว้ในคำถามทุบตีจะทำสิ่งที่ถูกถาม ตามที่จะ Perl ตามคำตอบด้านล่าง ดังนั้นข้อดีของการไม่ใช้ bash คืออะไร
steffen

คำตอบ:


67

อ๋อ มันถูกเรียกว่า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 :

หาก#!บรรทัดไม่มีคำว่า "perl" หรือคำว่า "indir" โปรแกรมที่ตั้งชื่อตามตัวอักษร#!จะถูกดำเนินการแทนตัวแปลภาษา Perl นี่เป็นสิ่งที่แปลกประหลาดเล็กน้อย แต่มันช่วยคนในเครื่องที่ไม่ทำ#!เพราะพวกเขาสามารถบอกโปรแกรมว่า SHELL ของพวกเขาคือ / usr / bin / perl และ Perl จะส่งโปรแกรมไปยังล่ามที่ถูกต้องสำหรับพวกเขา


40
นั่นเป็นเพียงสิ่งสกปรก
ผอม

1
นามสกุลไฟล์.jsทำงานด้วยหรือไม่
Pysis

1
#!นอกจากนี้สิ่งที่เครื่องไม่ได้ทำ ตอนนี้ฉันดูเหมือนจะมากขึ้นไปอีกและยังไม่เคยประสบปัญหานี้
Pysis

1
ตกลงเป็นเพียงตัวอย่างของคุณที่ดูเหมือนจะเน้นนามสกุลไฟล์จำนวนมากแทนที่จะแสดงหลายบรรทัด Shebang จากไฟล์และฉันคิดว่าฉันสันนิษฐานว่าเป็นวิธีการทำนายผล
Pysis

2
ฉันชอบวิธีที่man perlrunขี้อายยอมรับว่ามันเป็น "แปลกประหลาดเล็กน้อย" :) ฉันคิดว่าสิ่งนี้ควรได้รับการปฏิบัติเหมือนเป็นความอยากรู้อยากเห็นที่มุ่งเน้นไปที่สภาพแวดล้อมที่ไม่ใช่ UNIX และUNIX รุ่นเก่ามาก
บาง

25

สคริปต์ไม่จำเป็นต้องมี shebang

หากสคริปต์ถูกเรียกใช้จากล่ามคุณไม่สามารถแน่ใจได้ว่ามันมี shebang อยู่เลย สคริปต์ทำงานจากล่ามไม่จำเป็นต้อง shebang , ถ้าคุณเรียกล่ามในการเรียกใช้รหัส

คำตอบคือไม่ไม่มีคำสั่งที่จะตรวจสอบว่าภาษา (ล่าม) คืออะไรเพื่อเรียกใช้สคริปต์ด้วย อย่างไรก็ตามคุณสามารถดูข้างในสคริปต์ได้ตลอดเวลาและดูว่ามี Shebang ให้ค้นหาหรือไม่

กฎในระยะสั้น:

  1. เมื่อคุณเรียกใช้สคริปต์การเรียกล่ามจะทับ shebangs ที่เป็นไปได้ปฏิบัติการหรือไม่ Shebang หรือไม่ก็ได้
  2. หากไม่สามารถเรียกใช้งานได้และเรียกใช้จากล่ามสคริปต์จะต้องไม่มี shebang
  3. หากสคริปต์รันโดยไม่เรียกใช้ล่ามก่อนจำเป็นต้องใช้ (และใช้) shebang เพื่อค้นหาล่ามที่จะเรียกใช้และจำเป็นต้องเรียกใช้งานเพื่อให้มี "สิทธิ์" ในการเรียกล่ามจาก shebang

หากสคริปต์ไม่มี shebang จะไม่มีข้อมูล (direct *) ภายในสคริปต์เพื่อบอกให้ล่ามใช้

ต้องบอกว่า

แน่นอนคุณสามารถเขียนสคริปต์ตัวตัดคำเพื่อลองดูว่าสคริปต์นั้นมี shebang และอ่านล่ามจากที่นั้นหรือไม่ก็เรียกใช้จากล่ามที่พบ

ตัวอย่าง

#!/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")
  • บันทึกเป็นtryrunใน$PATH(เช่น~/binสร้างไดเรกทอรีหากไม่มีอยู่ออกจากระบบและกลับเข้ามาใหม่) ทำให้สามารถเรียกใช้งานได้ จากนั้นเรียกใช้:

    tryrun /path/to/nonexecutablescript

    เรียก (ทดสอบ) ล่ามที่ถูกต้องในสคริปต์ที่ไม่สามารถเรียกใช้งานได้pythonและbashสคริปต์ของฉัน

คำอธิบาย

  • สคริปต์จะอ่านบรรทัดแรกของสคริปต์เพียงลบ#!และใช้ส่วนที่เหลือเพื่อเรียกล่าม
  • ถ้ามันล้มเหลวที่จะเรียกล่ามที่ถูกต้องมันจะยกทั้งหรือPermissionErrorFileNotFoundError

บันทึก

ส่วนขยาย ( .sh, .pyฯลฯ ) เล่นบทบาทใด ๆ ในการกำหนดล่ามที่เหมาะสมบนลินุกซ์


(* แน่นอนว่าเป็นไปได้ในการพัฒนาอัลกอริธึม "smart" เพื่อกำหนดไวยากรณ์จากโค้ด)


ตกลงดังนั้นหมายความว่าแม้ว่า Linux จะมีการแยก Shebang ที่ใช้งานที่ไหนสักแห่ง (เพื่อให้สามารถเลือกล่ามที่ถูกต้องสำหรับ srcipts ที่ใช้งานได้) แต่ก็ไม่ได้จัดให้เป็นคำสั่งมาตรฐานแบบสแตนด์อโลน
Aivar

@Aivar การแยก shebang ไม่เป็นปัญหา แต่การรันโค้ดโดยที่ไม่สามารถทำได้อย่างสมบูรณ์
Jacob Vlijm

@Aivar Ah ฉันเห็นว่าคุณหมายถึงอะไร หากสคริปต์นั้นทำงานได้และทำงานโดยไม่มีภาษาในคำสั่งสคริปต์จะเรียกล่ามไม่ใช่วิธีอื่น
Jacob Vlijm

1
@JacobVlijm ฉันจะไม่พูดว่า "สคริปต์เรียก interpreter" เช่นเดียวกับ "เคอร์เนล Linux ใช้เส้น Shebang สำหรับการหาล่ามที่จะเรียกเมื่อเรียกใช้สคริปต์"
Paŭlo Ebermann

@ PaŭloEbermannขอบคุณ! จริงแน่นอน เคอร์เนลดูแลกระบวนการทั้งหมดด้วยวิธีใดวิธีหนึ่ง แต่เปรียบเปรยและฉันคิดว่าดีกว่าสำหรับการทำความเข้าใจคือการพูดว่าสคริปต์คือ "อนุญาต" เพื่อดูแลสิ่งที่ล่ามโทร (และทำจริง) ไม่แน่ใจเกี่ยวกับถ้อยคำ แต่ฉันอยากจะอธิบายมันราวกับว่ามีความคิดริเริ่มในสคริปต์ในขณะที่เคอร์เนลทำงานจริง
Jacob Vlijm

6

คุณสามารถทำสิ่งนี้ได้ด้วยสคริปต์เช่นนี้

#!/bin/bash

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

ดังนั้น:

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

ฉันไม่แนะนำให้ทำเช่นนี้ สิทธิ์จะมีเหตุผล นี่คือโปรแกรมสำหรับการยกเลิกการอนุญาต

โปรดทราบว่าการจัดการ shebang เป็นฟังก์ชั่นเคอร์เนล (ในซอร์สโค้ด Linux - fs/binfmt_script.c) โดยพื้นฐานแล้วกระบวนการที่เรียกใช้สคริปต์โดยตรงไม่ทราบเกี่ยวกับ#!- เคอร์เนลใช้สคริปต์เพื่ออธิบายว่าจำเป็นต้องเรียกใช้ล่าม


2
ฉันคิดเสมอว่านั่นเป็นหน้าที่ของเชลล์ไม่ใช่เคอร์เนล เรียนรู้สิ่งใหม่วันนี้
boatcoder

1
@boatcoder - เนื่องจากคุณสนใจให้เพิ่มลิงก์ไปยังที่ซึ่งซอร์สโค้ด Linux จัดการกับมัน
บาง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.