私はbashという単純な実行可能ファイルを実行していますhello
。ユーザー入力を要求し、応答を印刷します。私はこのように動作します./hello
。
プロンプトとユーザー入力の両方が現在のシェルで発生しますが、別のシェルで実行する必要があると思います。私がそう思うのは、ソースを使用して現在のシェルでexeファイルを実行できるからです。
これがどのように機能するかを説明できる人はいますか?
この問題の調査中、私は「シェル環境」と「シェルコンテキスト」という用語に頻繁に遭遇しました。彼らは同じですか?
答え1
「シェル環境」は、現在の環境変数を含む現在のシェルの環境を参照すると言うことができる。この環境は、開始されたサブプロセス(サブシェルまたはその他)によって継承されます。
「シェルコンテキスト」は一般的な用語であるが、「プロセスコンテキスト」と同じであると仮定する。シェルスクリプトの場合、これにはシェル環境だけでなく、現在のシェル変数、ファイル記述子(標準入力、標準出力、標準エラー、および明示的に開かれた他のすべての項目)、信号ハンドラ(使用済みtrap
)などが含まれます。 Cプログラムの場合、プロセスコンテキストはへの呼び出しから継承されますが、fork()
後続の呼び出しからは継承されませんexec()
。 (環境のみの呼び出しで維持されますexec()
。)
プログラムを実行するとhello
(シェルスクリプトと仮定)、入力と出力はhello
スクリプトを実行するシェルのコンテキスト内で発生します。これが「現在のシェル」です。入力したシェルは./hello
親シェルであり、hello
その環境を継承します。
内部的に親シェルが実行され、呼び出され、fork()
最終exec()
的にスクリプトを実行するシェルを起動しますhello
。
実際、hello
スクリプトは同じ場所にプロンプトを表示します。端末スクリプトを開始する場所は、スクリプトを実行するシェルが現在のフォアグラウンドプロセスであることを意味するためです。親シェルは完了するのを待っています。完了すると、親シェルが端末で再びフォアグラウンドプロセスになります。
source ./hello
スクリプトを使用または起動すると、. ./hello
スクリプトはコマンドを入力したシェルと同じコンテキストで実行されます。これは、対話型シェルのコンテキストと環境を変更できることを意味します。たとえば、現在の作業ディレクトリを変更したり(環境を変更したり)シグナルハンドラをインストールしたり(コンテキストを変更したり)、これらの変更はスクリプトの実行が完了したときにまだ「アクティブ」になります。
プログラムがコンパイルされたバイナリの場合、hello
呼び出しシェルの環境を継承しますが、そのコンテキスト(ファイル記述子など)を共有しません。シェルスクリプトではないため、サブシェルでは実際には実行されません。親シェルはバックグラウンドに移動し、シェルスクリプトのようにプログラムが完了するのを待ちます。親シェルの観点からは、コンパイルされたバイナリを実行することとシェルスクリプトを実行することには違いはありません。
シェルがバイナリを解釈する方法がわからないため、コンパイルされたバイナリはまたはsource
(ドット)で始めることはできません。.
この答えは少し手を振っていますが、基本的に正しいと思います。編集や追加が必要な部分がある場合は、コメント(または編集)を残してください。