だから私はこれについてかなりよく理解したと思いましたが、私はテストを試してみました(私が同意しない誰かの会話に答えて)私の理解に欠陥があることに気づきました...
できるだけ詳しく説明してください。シェルからファイルを実行すると、正確に何が起こりますか?つまり、./somefile some arguments
シェルに次のように入力してEnterキーを押すと(somefile
cwdに存在し、読み取り+実行権限がありますsomefile
)、後で何が起こりますか?
私アイデア正解は:
- シェルはシステムにシステムコールを実行して
exec
パスを渡します。somefile
- カーネルの確認
somefile
と参照マジックナンバープロセッサが処理できる形式であることを確認するためのファイルです。 - マジック番号がファイルがプロセッサが実行できる形式であることを示す場合
- 新しいプロセスの作成(プロセステーブルにエントリがあります)
somefile
メモリに読み込まれるかマップされます。スタックを作成し、コードのエントリポイントにジャンプを実行してから、パラメータsomefile
配列ARGV
(achar**
、["some","arguments"]
)で初期化します。
- マジックナンバーならシェルボーン次に、上記のように新しいプロセスを作成しますが、shebang(または)で参照し、次に渡されるインタプリタである実行可能
exec()
ファイルを使用します。/bin/bash
/bin/perl
somefile
STDIN
- ファイルに有効なマジック番号がない場合は、「無効なファイル(無効なマジック番号):Exec形式のエラー」などのエラーが発生します。
しかし、ファイルがプレーンテキストの場合、シェルは(私が入力したように)コマンドを実行しようとすると聞きましたbash somefile
。もともとは信じていなかったけど、いざやってみたらそれが合ったんですよ。だから、ここで実際に何が起こっているのかについては明らかに少し誤解があり、メカニズムを理解したいと思います。
シェルからファイルを実行すると、正確に何が起こりますか? (できるだけ詳しく...)
答え1
「Linuxでプログラムを実行する方法」に対する明確な答えは、次の2つの記事です。greennet.comタイトルは驚くべきことに、プログラムの仕組みそしてプログラムの実行方法:ELFバイナリ。最初の記事では、スクリプトを簡単に紹介します。 (技術的には最終的な答えはソースコードにありますが、これらの記事は読みやすく、ソースコードへのリンクを提供します。)
一部の実験では、ほぼ正しく実行され、単純なコマンドのリスト(shebangなし)を含むファイルの実行はシェルで処理する必要があることを示しています。これ実行(2)マンページには、テストプログラムexecveのソースコードが含まれています。これを使用して、シェルなしで何が起こるかを見てみましょう。まず、以下をtestscr1
含むテストスクリプトを作成します。
#!/bin/sh
pstree
そして別のものには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
始まり、2番目のシェルは(私のシステムで)スクリプトを実行するless
一般的なシェルでした。これはinで処理されます。sh
dash
pstree
zsh
zexecve
Src/exec.c
:shellはコマンドの実行に使用されますexecve(2)
。失敗した場合は、ファイルを読み取ってshebangがあるかどうかを確認し、それに応じて処理します(カーネルもこれを行います)。失敗すると、ファイルが存在している間にsh
ファイルを実行しようとします。ファイルにシャバンがありません。以下から0バイトを読んでください。
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
役に立つコメント(示されているように)タレジン):
一部のディスクファイルで定義されている単純なコマンドを実行します。
fork ()
- パイプ接続
- 検索コマンド
- リダイレクトする
execve ()
- 失敗した場合は、
execve
ファイルに実行モードが設定されていることを確認してください。その場合はディレクトリではなく、その内容はシェルスクリプトとして実行されます。
POSIX は、次の関数セットを定義します。exec(3)
機能、execve(2)
この機能をラップして提供します。ムル詳しくはお答えください。 Linuxでは、少なくともこれらの機能はカーネルではなくCライブラリによって実装されています。
答え2
これは、ある程度exec
使用される特定のホーム機能によって異なります。execve
、ようにスティーブンジッタ詳細に示すように、正しいバイナリ形式のファイルまたは正しいshebangで始まるスクリプトのみを実行してください。
しかし、そして、execlp
さらに一歩進んでください。execvp
shebangが正しくない場合は、/bin/sh
Linuxでファイルを実行してください。 ~から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機能ファミリの動作にどのような影響を与えるかです。以下は、行われたアクションの説明です。
プロセスイメージファイルがシステムに有効な実行可能ファイル(適切な権限を持つ実行可能で有効な形式)の場合、システムはファイルを実行します。
プロセスイメージファイルに適切な権限があり、実行可能であるがシステムに無効な形式(たとえば、他のアーキテクチャで認識されたバイナリ)の場合、これはエラーであり、errnoは[EINVAL]に設定されます(理由を参照)。後ろ ) on [EINVAL])。
プロセスイメージファイルに適切な権限があるが認識されない場合:
これがexeclp()またはexecvp()の呼び出しである場合は、コマンドソルバーを呼び出し、プロセスイメージファイルがシェルスクリプトであるとします。
execlp() または execvp() の呼び出しでない場合はエラーが発生し、errno は [ENOEXEC] に設定されます。
これはコマンドソルバーの取得方法を指定しないため、エラーが発生する必要はありません。だから私はLinux開発者がそのようなファイルを実行することを許可すると思います/bin/sh
。 (またはこれはすでに一般的な慣行なので、そのまま従います。)
今後、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
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.
その場合はディレクトリではなく、その内容はシェルスクリプトとして実行されます。
答え4
これはシェルスクリプトとして実行されます。いいえソース(たとえば、実行可能ファイル内に設定された変数は外部には影響しません)、おそらく遠い過去のアーティファクトでした。一つシェルと一つ実行可能な形式。実行可能ファイルではなく、シェルスクリプトである必要があります。