シェルでファイルを実行するとどうなりますか?


32

だから、私はこれをよく理解していると思ったが、テストを実行して(誰かに反対した会話に応じて)、私の理解に欠陥があることがわかりました...

可能な限り詳細に、シェルでファイルを実行すると正確に何が起こるのでしょうか?私が意味するのは、./somefile some argumentsシェルに入力somefileしてreturnキーを押すと(そしてcwdに存在し、読み取りと実行の許可がありますsomefile)、フードの下で何が起こるのですか?

私が考えた答えでした。

  1. シェルはにsyscallを作成しexec、パスを渡しますsomefile
  2. カーネルが調べsomefileではとルックスのマジックナンバーファイルのそれは、プロセッサが処理できる形式であるかどうかを判断します
  3. ファイルがプロセッサが実行できる形式であることをマジック番号が示している場合、
    1. 新しいプロセスが作成されます(プロセステーブルのエントリを使用)
    2. somefile読み取り/メモリにマップされます。スタックが作成され、実行のコードのエントリポイントにジャンプされるsomefileと、ARGVパラメータの配列に初期化(char**["some","arguments"]
  4. マジック番号がある場合シェバング次いで、exec()上記のように、新しいプロセスを生成するが、実行可能な使用は、インタプリタシェバング(例えばによって参照され/bin/bash又は/bin/perl)とsomefileに渡されSTDIN
  5. ファイルに有効なマジックナンバーがない場合、「無効なファイル(不良なマジックナンバー):Execフォーマットエラー」などのエラーが発生します。

ただし、ファイルがプレーンテキストの場合、シェルはコマンドを実行しようとします(入力したかのように)と誰かに言われましたbash somefile。私はこれを信じていませんでしたが、試しただけで、それは正しかったです。ですから、ここで実際に何が起こっているのかについて誤解があり、その仕組みを理解したいと思います。

シェルでファイルを実行するとどうなりますか?(詳細は合理的です...)


完全に理解するためにソースコードを見ることに代わるものはありません。
ワイルドカード

1
@Wildcardそれは私が今やっていることです、実際:-)できれば、私は自分の質問に答えます
ジョシュ

1
source somefile./somefileただし、によって分岐される新しいプロセスとは大きく異なります。
-thrig

@thrigはい、同意します。しかし、ファイルにマジックナンバーがなければ、./somefilebashがコマンドを実行することになるとは思いsomefileませんでした。私はそれがエラーを表示するだけで、代わりに効果的に見えると思ったsource somefile
ジョシュ

間違っsomefileています。テキストファイルの場合、実行しようとすると新しいシェルが生成されることを確認できます。ファイルecho $$を実行する場合とソースとする場合の動作は異なります。
ジョシュ

回答:


31

Linuxでの「プログラムの実行方法」に対する決定的な答えは、LWN.netの 2つの記事であり、驚くべきことに、「プログラムの実行方法」「プログラムの実行方法:ELFバイナリ」です。最初の記事では、スクリプトについて簡単に説明します。(厳密に言えば、決定的な答えはソースコードにありますが、これらの記事は読みやすく、ソースコードへのリンクを提供します。)

少し実験を行ったところ、ほぼ正しいことがわかりました。また、シェバンを使用せずにコマンドの単純なリストを含むファイルを実行するには、シェルで処理する必要があります。execve(2)のマンページは、テストプログラムはexecveのソースコードが含まれています。これを使用して、シェルなしで何が起こるかを確認します。最初にtestscr1、含むテストスクリプトを記述します

#!/bin/sh

pstree

もう1つ、testscr2のみを含む

pstree

両方を実行可能にし、両方がシェルから実行されることを確認します。

chmod u+x testscr[12]
./testscr1 | less
./testscr2 | less

今、もう一度試してくださいexecve(現在のディレクトリにビルドしたと仮定):

./execve ./testscr1
./execve ./testscr2

testscr1まだ実行されますが、testscr2生成します

execve: Exec format error

これは、シェルの処理がtestscr2異なることを示しています。ただし、スクリプト自体は処理しませんが、それでも使用/bin/shします。これは、以下にパイピングtestscr2することで確認できますless

./testscr2 | less -ppstree

私のシステムでは、

    |-gnome-terminal--+-4*[zsh]
    |                 |-zsh-+-less
    |                 |     `-sh---pstree

ご覧のとおり、私が使用していたシェルzshが起動しless、スクリプトを実行するための2番目のシェルshdashシステム上)が実行されましたpstree。でzsh、このによって処理されるzexecveSrc/exec.c:シェルの使用execve(2)コマンドを実行しようとすると、それが失敗した場合、それに応じて(カーネルも行っています)、それを処理し、それはシェバングを持っているかどうかを確認するために、ファイルを読み込んで、その場合は失敗すると、ファイルshからゼロバイトを読み取らなかった限り、でファイルを実行しようとします。

        for (t0 = 0; t0 != ct; t0++)
            if (!execvebuf[t0])
                break;
        if (t0 == ct) {
            argv[-1] = "sh";
            winch_unblock();
            execve("/bin/sh", argv - 1, newenvp);
        }

bash同じ動作をexecute_cmd.c持ち、有用なコメントで実装されています(taliezinが指摘したとおり):

できればディスクファイルで定義されている単純なコマンドを実行します。

  1. fork ()
  2. パイプを接続する
  3. コマンドを調べる
  4. リダイレクトを行う
  5. execve ()
  6. 場合はexecve失敗したファイルは、実行可能なモードが設定されている場合は、参照してください。その場合、ディレクトリではない場合、その内容をシェルスクリプトとして実行します。

POSIXはとして知られている、機能のセットを定義関数、どのラップあまりにもこの機能を提供します。詳細については、muruの回答を参照してください。Linuxでは、少なくともこれらの機能はカーネルではなくCライブラリによって実装されます。exec(3)execve(2)


これは素晴らしく、私が探していた詳細があります、ありがとう!
ジョシュ

12

部分的には、これはexec使用される特定のファミリ関数に依存します。execveStephen Kittが詳細に示したように、正しいバイナリ形式のファイル、または適切なシバンで始まるスクリプトのみを実行します。

しかしexeclpそしてexecvpさらに一歩を行く:シェバングが正しくなかった場合、ファイルがで実行される/bin/shLinux上で。からman 3 exec

Special semantics for execlp() and execvp()
   The execlp(), execvp(), and execvpe() functions duplicate the actions
   of the shell in searching for an executable file if the specified
   filename does not contain a slash (/) character.

   If the header of a file isn't recognized (the attempted execve(2)
   failed with the error ENOEXEC), these functions will execute the
   shell (/bin/sh) with the path of the file as its first argument.  (If
   this attempt fails, no further searching is done.)

これは、POSIX(エンファシスマイニング)である程度サポートされています。

標準開発者が指摘する潜在的な混乱の原因の1つは、プロセスイメージファイルの内容がexecファミリの関数の動作にどのように影響するかということです。以下は、実行されるアクションの説明です。

  1. プロセスイメージファイルがこのシステムの有効な実行可能ファイル(実行可能かつ有効で適切な特権を持つ形式)である場合、システムはファイルを実行します。

  2. プロセスイメージファイルに適切な特権があり、実行可能であるがこのシステムに対して有効でない形式(別のアーキテクチャの認識されたバイナリなど)である場合、これはエラーであり、errnoは[EINVAL]に設定されます[EINVAL])。

  3. プロセスイメージファイルに適切な特権があるが、他の方法で認識されない場合:

    1. これがexeclp()またはexecvp()の呼び出しである場合、プロセスイメージファイルがシェルスクリプトであると想定してコマンドインタープリターを呼び出します。

    2. これがexeclp()またはexecvp()の呼び出しでない場合、エラーが発生し、errnoが[ENOEXEC]に設定されます。

これはコマンドインタープリターの取得方法を指定しませんが、エラーを与える必要があることを指定しません。したがって、Linux開発者はそのようなファイルの実行を許可していると思います/bin/sh(または、これはすでに一般的な慣行であり、彼らはそれに従いました)。

FWIW、FreeBSDのマンページexec(3)も同様の動作に言及しています:

 Some of these functions have special semantics.

 The functions execlp(), execvp(), and execvP() will duplicate the actions
 of the shell in searching for an executable file if the specified file
 name does not contain a slash ``/'' character. 
 If the header of a file is not recognized (the attempted execve()
 returned ENOEXEC), these functions will execute the shell with the path
 of the file as its first argument.  (If this attempt fails, no further
 searching is done.)

しかしAFAICTは、おそらく環境をより細かく制御するために、一般的なシェルを使用しexeclpたりexecvp直接使用したりすることはありません。それらはすべて、を使用して同じロジックを実装しexecveます。


3
私はまた、Linux上で、少なくともそれを追加したい、execlexeclpexecleexecvexecvpexecvpeするすべてのフロントエンドですexecveシステムコールは、前者はCライブラリによって提供され、カーネルはexecve(そしてexecveat最近では)知っているだけです。
スティーブンキット

@StephenKittそれは、man7.orgのセクション2でこれらの関数のマンページが見つからなかった理由を説明しています。
muru

6

これはbash、ファイル内のソースからのコメントとして、Stephen Kittの回答に追加される可能性がありますexecute_cmd.c

できればディスクファイルで定義されている単純なコマンドを実行します。

1. fork ()
2. connect pipes
3. look up the command
4. do redirections
5. execve ()
6. If the execve failed, see if the file has executable mode set.  

その場合、ディレクトリではない場合、その内容をシェルスクリプトとして実行します。


0

シェルスクリプトとして実行され、ソースされません(たとえば、実行されたファイルに設定された変数は外部に影響しません)。おそらく、1つのシェルと1つの実行可能な形式があった霧の過去からの痕跡です。実行可能ファイルではなく、シェルスクリプトである必要があります。


2
あなたは私の質問を誤解しています。何が起こるの詳細に?少なくとも、私はシバンをチェックするものを理解する必要があります、exec()それはシェルですか?かなり多くの内部が必要です
ジョシュ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.