与えるか言うか

与えるか言うか

shebangでプログラムを使用したいので、<myscript>というスクリプトを作成します。

#!<mypgm>

また、コマンドプロンプトから<mypgm>を直接実行できることを願っています。

<mypgm> args...

これまでは問題ありません。

パラメータを使用してコマンドプロンプトで<myscript>を実行できるようにしたいです。

<myscript> blabla

その後、shebangは次のパラメータを使用して<mypgm>を呼び出します。

<mypgm> <myscript> blabla

shebangを使っていつ<mypgm> <myscript> blablaを呼び出すべきかを知る必要があります。

myscript blabla # uses the shebang
-or-
<mypgm> myscript blabla   # directly in the command prompt.

環境変数を確認しました(編集:<====偽の主張(??、??」))、プロセステーブル(また親プロセス)にありますが、違いを作成する方法が見つかりませんでした。

これまで私が見つけた唯一のことは次のとおりです。

grep nonvoluntary_ctxt_switches /proc/$$/status

その行がshebangの直後にある場合、shebangを介して呼び出す場合、値は通常2(時々3)、直接呼び出す場合は通常1(時々2)です。不安定でプロセススケジューリング(プロセスがCPUから切り離される回数)に依存しているので、ここでより良い解決策がある人がいるかどうか疑問に思います。

答え1

myprgそれがshebangで使用されているかどうかを魔法のように検出するのではなく、コマンドライン-fフラグ(たとえば)を使用してファイルをスクリプトに渡して明示的に作成するのはどうですか?

コメントの例では:

上記の計算理論の例では。 calc PI + 14.14159を返す必要があります... shebang(つまり、最初の引数としてファイル名)のサポートを追加すると、ファイルに含まれる計算が返されます。

calcスクリプトファイルをインポートし、-f次のコマンドを使用してスクリプトを作成します。

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

ファイルを呼び出してaddone.calc実行可能にしたとしましょう。その後、次のように呼び出すことができます。

$ ./addone.calc PI
4.141592...

呼び出しはへの呼び出しに変換されるため、どの引数が/usr/local/bin/calc -f ./addone.calc PIスクリプトファイルであり、どの引数がスクリプトの引数であるかがわかります。

awkこれは行動パターンと行動に似ていますsed

似ているが逆のアプローチは、calc基本的にスクリプトファイル引数を使用します(shebangとの使用を簡素化します)、コマンドラインフラグを追加して引数の式と一緒に使用することです。これも同様に機能しますsh -c '...'

答え2

実際の問題はデザインです<mypgm>。引数を解釈する2つの方法をサポートするのではなく、それを呼び出す2つの方法を提供してください。

shebangコマンドは、スクリプトの内容を実行するスクリプトエンジンまたは他のものですが、bash実行するperlスクリプトのファイル名で呼び出されると予想されます。どうbashやってやるの?推測しません。オプション(またはオプションの引数)のように見えない引数が見つかった場合は、それを実行するスクリプトと見なし、後続の引数がスクリプトに渡されます。たとえば、

/bin/bash -x -e somename foo bar

ここでbashはファイルを見つけて引数somenameと 。あなたも同じことをしなければならないので、あなたはfoobar可能<mypgm> <myscript>いつかはコマンドラインに文を書きたいです。

デフォルトでは、スクリプトを使用したくない場合は<mypgm>パススルースクリプトが必要です<mypgm> -f <myscript>。あなたはそうしsedなかった方法。その後、次のようにshebang行で使用できます。

#!<mypgm> -f

bashたとえば、およびを使用してスクリプトの大文字と小文字をデフォルトにするには、perl「今回はスクリプトなし」オプションを作成します。--これを使用すると、スクリプト(または他のもの)で実行しようとしない可能性が<mypgm> -- one two threeあります。oneこの場合、shebang行には次のようにのみ表示されます。

#!<mypgm>

答え3

今shebangを使用していつblablaを呼び出すべきかを知る必要があります。

Cでは、次のようにしてその情報を取得できます。getauxval(AT_EXECFN)、元の実行可能ファイルの名前(つまり、に渡された最初の引数execve(2))を示します[1]。

ただし、文字列はコマンドライン引数と環境文字列の直後、メモリ領域の末尾に配置されるため、[stack]そこから直接取得できます。

たとえば、次のPerlスクリプト(名前foo.pl)で直接実行し、次のように実行可能にした場合chmod 755 foo.pl./foo.pl/usr/bin/perlperl ./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";

最新(> = 3.5)Linuxカーネルには環境の終わりがあるかもしれません/proc/PID/stat(文書の説明に従ってフィールド51)。proc(5)マンページ)。

#! /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] 2.6.26以降のLinuxカーネルには、それを指す補助ベクトルエントリが導入されました(参照:犯罪)しかし、実行可能ファイル名はそれよりも長い前(1996年のlinux-2.0以降)スタックの最後で使用できました。

答え4

次の環境変数がすべてのタスクを実行することに気づきました。 $_

<myscript>を使用して起動すると、その値は「./<myscript>」です。

<mypgm> <myscript> で始まる場合、その値は <mypgm> のフルパスです。

私の場合は、次のように簡単です。

#!/bin/bash

how_called=$_

if [[ "X$how_called" == X$0 || "X$how_called" ==X$BASH ]]; then
#                              ^in this case, if the login shell is not bash
   shebang=0
else
   shebang=1
fi

bn=$(basename $0)

後で(私の目的のために):

if (( shebang == 1 )) || [[ ! -z $1 && "X$1" != X-* && "X$1" == X*\.${bn:0:3} && -x $1 ]]; then 
   # ^ shebang: first argument is the script file
   #                        ^ or not shebang: first argument **may** be a script file name
   #                                                    ^ ensure that this is a script by script extension
   #                                                       (otherwise just use the more verbose but standard --script=...)

   shebang_fn="$1"
   shift 1
   set -- --script="$shebang_fn" "$@" # fall back on standard way.
fi

(ここでテーブルを少し反転していることを知っていますが、これが移植可能なソリューションであることを確認する必要があります)。

関連情報