シェル組み込みコマンドについて


12

中には、bashのマニュアル、次のことが書かれています

Builtin commands are contained >>> within <<< the shell itself

また、この答えは、

A built-in command is simply a command that the shell carries out itself,
instead of interpreting it as a request to load and run some
>>> other program <<<

compgen -bbash 4.4で実行すると、すべてのシェル組み込みコマンドのリストが表示されます。私はその一例を参照[し、killシェルの組み込みコマンドであることを記載されています。しかし、実際の場所は次のとおりです。

/usr/bin/[
/bin/kill

builtinコマンドが/bin/bash実行可能ファイルにコンパイルされるという意味だと思いました。だから私を本当に混乱させているのは何builtinですか:私を訂正してください、しかしそれが実際にシェルの一部ではない場合、どのようにして別のコマンドをにすることができますか?


1
一部のコマンドは、元々個別のユーティリティとして存在していました。現在は、POSIX標準への準拠、移植性、および下位互換性のために存在しています。シェルは、パフォーマンスのために組み込まれたものをいくつか実装しています。他の理由もあるかもしれませんが、それはあまり詳細ではありません。
Sergiy Kolodyazhnyy

1
私が考えるもう1つの理由は、execファイル記述子の操作やeval コマンドの評価など、シェル固有の組み込みコマンドが必要なためです。これらはスタンドアロンコマンドとして必要ではありません
Sergiy Kolodyazhnyy

回答:


16

シェルに組み込まれているコマンドは、パフォーマンスが向上するために組み込まれることがよくあります。たとえば、外部の 呼び出しはprintf、組み込みの呼び出しを使用するよりも遅くなりますprintf

一部のユーティリティは組み込みである必要がないため、などの特別なものでない限り、外部ユーティリティcdとしても提供されています。これは、組み込みの同等の機能を提供しないシェルによってスクリプトが解釈されてもスクリプトが壊れないようにするためです。

一部のシェルのビルトインは、外部の同等のコマンドに対する拡張機能も提供します。printfたとえば、バッシュは

$ printf -v message 'Hello %s' "world"
$ echo "$message"
Hello world

(変数に出力します)/usr/bin/printf現在のシェルセッションのシェル変数にアクセスできないため(そしてそれらを変更できないため)、外部では実行できません。

組み込みユーティリティには、拡張されたコマンドラインを特定の長さよりも短くする必要があるという制限もありませ。している

printf '%s\n' *

したがってprintf、シェルの組み込みコマンドであれば安全です。コマンドラインの長さの制限は、execve()外部コマンドの実行に使用されるCライブラリ関数に起因します。コマンドラインと現在の環境がARG_MAXバイトよりも大きい場合(getconf ARG_MAXシェルを参照)、への呼び出しexecve()は失敗します。ユーティリティがシェルに組み込まれている場合は、execve()呼び出す必要はありません。

組み込みユーティリティは、にあるユーティリティよりも優先されます$PATH。の組み込みコマンドを無効にするにはbash、例えば

enable -n printf

シェルに組み込む必要のあるユーティリティの短いリストがあります(POSIX標準の特別な組み込みリストから取得)

break
colon (:)
continue
dot (.)
eval
exec
exit
export
readonly
return
set
shift
times
trap
unset

これらは、現在のシェルセッションの環境とプログラムフローを直接操作するため、組み込みが必要です。外部のユーティリティはそれを行うことができません。

興味深いことに、cdこれはこのリストの一部ではありませんが、POSIX はそのことについて次のように述べています

以来cd、現在のシェル実行環境に影響を与え、それが常に内蔵のシェルレギュラーとして提供されます。サブシェルまたは別のユーティリティ実行環境(次のいずれかなど)で呼び出された場合:

(cd /tmp)
nohup cd
find . -exec cd {} \;

呼び出し元の環境の作業ディレクトリには影響しません。

したがってcd、理論的には可能ですが、「特別な」ビルトインには外部の対応物を含めることはできないと想定しています(ただし、あまり機能しません)。


IIRC、chdir/ cdは、fork導入される前の非常に初期のUnices / pre-Unixの外部バイナリでした。
Xophmeister

@Xophmeister Solaris 11.4(ベータ版)にはまだが/usr/bin/cdありますが、現在の作業ディレクトリは実際には変更されません。そのマニュアルによると:/usr/bin/cd呼び出しプロセスには影響しませんが、特定のディレクトリを現在のディレクトリとして設定できるかどうかを判断するために使用できます。
クサラナンダ

2
ビルトインのもう1つのかなり具体的な理由:ビルトインkillは、別のプロセスをフォークする必要がないため、いいです。プロセス数の制限に達した場合に適しています。
デロベルト

7

一部のビルトインはビルトイン外部コマンドの両方として存在するという事実に(非常に理解できるほど)混乱しています。したがって、たとえばコマンドがあるというのは正しいですが、「実際の場所」がにあるという意味ではありません。/bin/[/bin

これをテストする簡単な方法は、コマンドで使用可能なすべてのインスタンスを表示typeする-aスイッチで実行することです。私のArchシステムでは、次のように表示されます。

$ type -a [
[ is a shell builtin
[ is /sbin/[
[ is /usr/sbin/[
[ is /usr/bin/[

なお/sbin/usr/sbin及び/binを指しているすべてのシンボリックリンクされている/usr/binので、唯一の外部のものがあります、[

$ readlink -f /usr/sbin /sbin /bin/
/usr/bin
/usr/bin
/usr/bin

ご覧のとおり、[は組み込みコマンドと外部コマンドの両方であり、同じことが他のさまざまなシェル組み込みコマンドにも当てはまります。しかし、それはそれらがシェル自体にコンパイルされたシェル組み込みであるという事実を変更しません。


なぜディストリビューションなのか。既存の内部コマンドに別の外部コマンドを提供しますか?なぜ複製するのですか?
LoveWithMaths 2018年

1
@linuxuserこれらのユーティリティのいくつかはPOSIXで必要とされ、ユーザーがたまたま使用しているシェルが組み込みを提供するかどうかもわかりません。OSの内部コマンドとは考えないでください。これらはシェルの内部コマンドにすぎず、シェルは変更できます。
terdon

内部コマンドがシェルによって提供されているかどうか、私は疑いました。次に、外部コマンドを提供するのは誰ですか?内部および外部コマンドとして利用できる多くのコマンドを観察したように、私はそれらを明示的にインストールしました。だから誰が外部コマンドを提供しますか?ディストリビューションはそれらを正しく提供しますか?
LoveWithMaths

@linuxuserは、コマンドとオペレーティングシステムによって異なります。たとえば、私のArch Linuxでは、/bin/printfcoreutilsパッケージと/bin/killによってインストールされますutil-linux
terdon

申し訳ありませんが、まだわかりません。上記のどれがディストリビューションによって提供されますか?そして、それを提供するディストリビューションによって提供されていない他の人はどうですか?
LoveWithMaths
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.