スクリプトの代わりにシェルに「コマンド」を提供するとどうなりますか?

スクリプトの代わりにシェルに「コマンド」を提供するとどうなりますか?

この質問のバリエーションが何度も要求されました(ここそしてここ、例えば)しかし、答えが私の質問を完全に捉えていないか、私が知っているよりも多くを想定するのは心配です。

たとえば、質問をしますが、おおよそ私が理解しようとしているのは(1)どのようにシェルは実行可能ファイルとスクリプトを認識できますが、もしそうなら(2)認識後に次に何が起こるのか?

私の作業ディレクトリにシェルスクリプトと実行可能ファイルがあるとしますscript(「実行可能」はバイナリ「マシンコード」を意味すると理解していますが、正確ではないかもしれません)exe。 bashシェルと対話していて、scriptbashとtcshの両方がこれを実行できるとしましょう。さらに、最初の行を仮定すると確かにShebangで始めましょう#!...

  1. scriptコマンドラインプロンプトに入力するとします。 Bashはこれが実行可能ファイルではなくスクリプトであるかどうかを判断し、判断したら何をしますか? (私の考えに答えると、「新しいプロセス、特に新しいシェル(サブシェルなど)を作成し、この場合bash(shebangがないため)を作成し、その中にあるスクリプトからコマンドを実行することです」と思います。わからない。)

  2. exeそれでは、コマンドラインプロンプトに入力したとします。 Bashはこれがスクリプトではなく実行可能ファイルであるかどうかを判断しますか?一度決定したら何をしますか? (私の考えでは、「新しいプロセスを作成して実行可能ファイルが完了するのを待つ」という答えが出てくるようですが、わかりません。)

  3. それでは、最初の行にscript含めるように変更したとしましょう。#! /bin/tcshbashはこれがスクリプト((1)への答えでshebangが何を変更しますか?)であり、実行可能ファイルではないことをどのように決定し、決定したら何をしますか? (私の考えに答えると、「新しいプロセス、特に新しいシェル(つまりサブシェル)を作成し、この場合はtcsh(私はshebangだから)を作成し、その中のスクリプトでコマンドを実行することです」と思います。私はそうではありません。

ベストアンサー1

まず、コマンドを実行するシステムがあります。

このシェルコードを使用すると:

cmd and its args

シェルは、リストされているディレクトリー内のcmd別名、関数、組み込み、および実行可能ファイル(実行権限を持つ通常のファイル)を探します$PATH(現在の作業ディレクトリーがそのディレクトリーにない限り、$PATHこれは悪い習慣です)。 。

後者の場合、execve()通常は3つの引数を使用して子プロセスからシステムコールを呼び出します。

  1. ファイルパス( /path/to/cmd)
  2. パラメータリスト(["cmd", "and", "its", "args", 0]
  3. var=valueエクスポートされた各変数の文字列のリスト。

execve()ファイルの種類に応じてファイルを処理する場合:

  • ELFバイナリ実行可能ファイルの場合は、そのファイル(またはその一部)をメモリにロード/マッピングし、より多くの共有ライブラリをロードして実行を開始する動的リンカーも可能です。
  • で始まる場合#!(シェルではない)、行の残りの部分を実行する別のファイルとして解釈し、ファイルパスをコマンドの追加引数として渡します。 (もしそうなら#! foo bar、同じことをしますexecve("foo", ["foo" or "cmd", "bar", "/path/to/cmd", "and", "its", "args"], env))。
  • システムはELFに加えてさまざまなデフォルトの実行可能ファイル形式をサポートでき、一部のシステムはインタプリタをファイルの先頭に一致するパターンに関連付けるように設定できます(Linuxのbinfmt_miscを参照)。

プロセスメモリは、プロセス中にほとんど消去され、プロセスが実行可能ファイルexecve()でコードを実行しているため、決して返されません。

ファイルの種類が認識されない場合は、エラーコードに戻り(失敗表示)execve()されます。-1ENOEXEC

この場合、POSIXシェルが必要であり、これをスクリプトとして処理するには、execlp()C関数(システムコールではない)やenv/ ...(または通常はPOSIXツールボックスでコマンドを実行するために使用されるすべての項目)find -execなどが必要shです。ランダムに実行されるのを避けるために経験的な方法を使用しているようですsh

shほとんどのシェルは shebang があるかのように実行してこれを行います#! /path/to/the/standard/sh -。一部はPOSIX準拠のsh実装であるか、サブプロセスでファイル自体を解釈してこれを実行するPOSIX shモードを使用します。

したがって、3つのシナリオの場合:

  1. shebang-lessの代わりにscript実行すると機能します。シェルは子プロセスで実行され、既知の形式ではないため、ENOEXECで失敗するため、シェルは(オプションで)どのように見えるかを確認します。内で実行できます。構文(またはバリアント)またはそれ自体で解釈されます(親シェルプロセスは終了するのを待ちます)。./scriptscript/usr/bin/scriptexecve("./script", ["./script", 0], env)execve()shexecve("/bin/sh", ["sh", "-", "./script"])argv[0]-
  2. ./exe:shellはexecve("./exe", ["./exe", 0], env)子プロセスでこれを行い、子プロセスは成功し、親プロセスはそのタスクが終了するのを待ちます。
  3. ./script#! /bin/tcshshebang:shellを使用すると、execve("./script", ["./script", 0], env)システムはそれをスクリプトとして認識するため、成功することもできます。パラメータを使用して順番に実行されexecve()ます。親シェルは通常どおりサブシェルを待ちます。/bin/tcsh./script

おすすめ記事