GNU/Linux >> Belajar Linux >  >> Linux

shebang atau bukan shebang

Alih-alih memiliki myprg secara ajaib mendeteksi apakah itu digunakan dalam shebang, mengapa tidak membuatnya eksplisit dengan menggunakan bendera baris perintah (seperti -f ) untuk memberikannya file sebagai skrip?

Dari contoh Anda di komentar:

Dalam contoh teori kalk di atas. calc PI + 1 harus mengembalikan 4,14159... Sekarang menambahkan dukungan untuk shebang (yaitu nama file sebagai parameter pertama) akan mengembalikan perhitungan yang terkandung ke dalam file.

Buat calc ambil file skrip melalui -f lalu buat skrip dengan:

#!/usr/local/bin/calc -f
$1 + 1

Katakanlah Anda menyebut file ini addone.calc dan membuatnya dapat dieksekusi. Kemudian Anda dapat memanggilnya dengan:

$ ./addone.calc PI
4.141592...

Panggilan itu akan diterjemahkan menjadi doa /usr/local/bin/calc -f ./addone.calc PI , jadi cukup jelas argumen mana yang merupakan file skrip dan mana yang merupakan parameter skrip.

Ini mirip dengan cara awk dan sed berperilaku.

Pendekatan serupa (tetapi berlawanan) adalah memiliki calc ambil argumen file skrip secara default (yang menyederhanakan penggunaannya dengan shebang), tetapi tambahkan flag baris perintah untuk menggunakannya dengan ekspresi dari argumen. Ini mirip dengan bagaimana sh -c '...' berfungsi.


Masalah sebenarnya adalah cara Anda mendesain sintaks baris perintah <mypgm> . Alih-alih mencoba mendukung dua cara untuk menginterpretasikan argumennya, berikan dua cara untuk menyebutnya sebagai gantinya.

Perintah Shebang dimaksudkan sebagai mesin skrip yang menjalankan konten skrip Anda; mungkin bash , perl , atau apa pun, tetapi diharapkan itu dipanggil dengan nama file skrip untuk dieksekusi. Bagaimana bash lakukan? Itu tidak menebak. Jika menemukan argumen yang tidak terlihat seperti opsi (atau argumen opsi), ia akan memperlakukannya sebagai skrip untuk dieksekusi; argumen setelah itu diteruskan ke skrip. Misalnya:

/bin/bash -x -e somename foo bar

Di sini, bash akan mencari file somename dan coba jalankan sebagai skrip dengan argumen foo dan bar . Anda harus melakukan hal yang sama, karena Anda mungkin ingin menulis <mypgm> <myscript> pada baris perintah suatu hari nanti.

Jika Anda ingin menggunakan <mypgm> tanpa skrip sebagai default, Anda dapat meminta skrip untuk diteruskan dengan <mypgm> -f <myscript> . Ini adalah bagaimana sed melakukannya. Maka Anda akan menggunakannya dalam garis shebang seperti ini:

#!<mypgm> -f

Jika Anda ingin case skrip menjadi default, seperti dengan bash dan perl , buat opsi yang mengatakan "tidak ada skrip saat ini". Anda bisa menggunakan -- untuk ini, sehingga <mypgm> -- one two three tidak mencoba menjalankan one (atau apa pun) sebagai skrip. Dalam hal ini, baris shebang hanya akan berbunyi:

#!<mypgm>

Sekarang, saya perlu tahu kapan blabla dipanggil menggunakan shebang, atau tidak:

Di C, Anda bisa mendapatkan info itu melalui getauxval(AT_EXECFN) , yang akan memberi tahu Anda nama asli yang dapat dieksekusi (yaitu argumen pertama diteruskan ke execve(2) ) [1].

Tapi string itu ditempatkan di memori segera setelah argumen baris perintah dan string lingkungan, di akhir [stack] wilayah memori, sehingga dapat diambil langsung dari sana.

Misalnya, skrip perl berikut (beri nama foo.pl ), jika dibuat dapat dieksekusi dengan chmod 755 foo.pl , akan mencetak ./foo.pl saat dijalankan secara langsung dan /usr/bin/perl saat dijalankan sebagai perl ./foo.pl :

#! /usr/bin/perl

open my $maps, "/proc/self/maps" or die "open /proc/self/maps: $!";
my $se;
while(<$maps>){ $se = hex($1), last if /^\w+-(\w+).*\[stack\]$/ }
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
sysseek $mem, $se - 512, 0;
sysread $mem, $d, 512 or die "sysread: $!";
print $d =~ /([^\0]+)\0+$/, "\n";

Pada kernel linux yang lebih baru (>=3.5), akhir lingkungan juga tersedia di /proc/PID/stat (di kolom ke-51, seperti yang didokumentasikan di proc(5) halaman manual).

#! /usr/bin/perl

open my $sh, "/proc/self/stat" or die "open /proc/self/stat: $!";
my @s = <$sh> =~ /\(.*\)|\S+/g;
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
seek $mem, $s[50], 0;
$/ = "\0";
my $pn = <$mem> or die "readline: $!"; chomp $pn; print "$pn\n";

[1] Kernel Linux yang lebih baru dari 2.6.26 memperkenalkan entri vektor aux yang menunjuk ke sana (lihat komit), tetapi nama yang dapat dieksekusi tersedia di akhir tumpukan jauh sebelum itu (sejak linux-2.0 dari 1996).


Linux
  1. dos2unix:perintah tidak ditemukan

  2. chmod:perintah tidak ditemukan

  3. mkfs:perintah tidak ditemukan

  1. file:perintah tidak ditemukan

  2. tune2fs:perintah tidak ditemukan

  3. fsck:perintah tidak ditemukan

  1. ekor:perintah tidak ditemukan

  2. nohup:perintah tidak ditemukan

  3. Bagaimana cara mengatur file sebagai TIDAK dapat dieksekusi?