$ which echo
echo: Shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat
Echoがls
、ps
、cat
などの独立したユーティリティではないのはなぜですか?なぜシェル固有なのですか?何か良い理由はありますか?
ビルトインには2つのクラスがあります。
一部のコマンドは、外部にあると機能しないため、シェルプログラム自体に組み込む必要があります。
cd
は、外部の場合、独自のディレクトリしか変更できないため、その1つです。シェルの現在の作業ディレクトリには影響しません。 (参照: cd
がプログラムではない理由 )
他のクラスのコマンドは、純粋に効率のためにシェルに組み込まれています。
dash
man page には、このクラスのコマンドの例としてprintf
、echo
、およびtest
について言及している組み込みのセクションがあります。
Unixシステムには、常にその2番目のクラスのコマンド用の個別の実行可能ファイルが含まれています。これらの個別の実行可能ファイルは、使用する可能性のあるすべてのシェルにも組み込まれていますが、私が使用したすべてのUnixyシステムで引き続き使用できます。 ( [〜#〜] posix [〜#〜] 実際には、これらの実行可能ファイルが存在する必要があります。)
echo
がAT&T Unix System V Release 3.1のシェルに組み込まれたと思います。 AT&Tのマニュアルの2つの異なるエディションの比較に基づいています B1シリーズUnixシステム 。誰かが親切にこれらのマニュアルの1986年版をスキャンし、 それらをオンラインに置く ;これらはSVR3のオリジナルリリースに対応しています。 echo
が NIX System Vユーザーズマニュアル、ボリュームII の523ページのリストにないことがわかります。コマンドが組み込まれている場合は、シェル。私の地元の1987年のSVR3.1マニュアルの紙のコピーでは、echo
isがマニュアルのこのセクションにリストされています。
これはバークレーではないと確信しています [〜#〜] csrg [〜#〜] AT&Tが持ち帰ったイノベーション。 4.3BSDは1986年のSVR3と同じ年にリリースされましたが、 4.3BSDのsh.1マンページ を見ると、echo
が「特殊コマンド」セクションの組み込みコマンドのリストにないことがわかります。 CSRGがこれを行った場合、文書化されたソースにそれを証明してもらいたいと思います。
この時点で、echo
がSVR3.1よりも前にシェルに組み込まれていたのか、それともそれまでdocumentedではなかったのか疑問に思われるかもしれません。私が利用できる最新のSVR3より前のAT&T Unixソースコードは PDP-11 System III tarball にあり、Bourne Shellソースコードがあります。 /usr/src/cmd/sh/msg.c
にある組み込みコマンドテーブルにはecho
はありません。そのファイルのタイムスタンプに基づいて、echo
が1980年にシェルになかったことを証明します。
同じディレクトリにはbuiltin.c
というファイルも含まれていますが、この質問に対するオンポイントは含まれていませんが、興味深いコメントが見つかりました。
/*
builtin commands are those that Bourne did not intend
to be part of his Shell.
Redirection of i/o, or rather the lack of it, is still a
problem..
*/
一部のコマンドが組み込まれている3つ目の理由があります。外部コマンドの実行が不可能な場合に使用できます。
システムが壊れてls
コマンドが機能しない場合があります。場合によっては、echo *
は引き続き機能します。
もう1つの(より重要な!)例はkill
です。システムで空きPIDが不足すると、/bin/kill
(PIDが必要になるため:-)を実行できませんが、組み込みkill
は機能します。
ところで、which
は外部コマンドであるため(少なくともbashでは内部コマンドではありません)、内部コマンドをリストすることはできません。例えば:
$ which echo
/bin/echo
$ type -a echo
echo is a Shell builtin
echo is /bin/echo
Bashリファレンスマニュアル によると、それは利便性についてです。
シェルはまた、別個のユーティリティを介して取得することが不可能または不便な機能を実装する組み込みコマンド(ビルトイン)の小さなセットを提供します。たとえば、cd、break、continue、およびexec)は、シェル自体を直接操作するため、シェルの外部には実装できません。特に、history、getopts、kill、またはpwdビルトインは、個別のユーティリティで実装できますが、組み込みコマンドとして使用する方が便利です。シェルのすべての組み込みについては、後続のセクションで説明します。
Advanced Bash Scripting Guide には、より詳細な説明があります。
「組み込みは、文字通り組み込みのBashツールセット内に含まれるコマンドです。これは、パフォーマンス上の理由のどちらかです。組み込みは、通常、フォークする必要がある外部コマンドよりも速く実行されます 1 別のプロセス-または、特定のビルトインがシェルの内部に直接アクセスする必要があるためです。」
echo
は、一部のシステムではスタンドアロンユーティリティとして存在することにも注意してください。これが私のDarwinシステム(MacOSX 10.5.8-Leopard)にあるものです
$ uname -a
Darwin Host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-Apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo
echo
はビルトインとしても利用できますが、私のスクリプトは私のMacでは/ bin/echoを使用し、ほとんどのLinuxおよびFreeBSDシステムではBashビルトインを使用しているようです。しかし、スクリプトは依然としてどこでも問題なく動作するため、問題はないようです。
Bhmの答えを補足するために、/bin
がPATH
から誤って削除されました。 echo $PATH
それを見つけるためですよね?
現在、ほとんどのシェルには組み込みのecho
が含まれていますが、GNU CoreUtilsにはスタンドアロンの実装も含まれています。
$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo
GNU Coreutilsがインストールされていないようです(ほとんどのLinuxベースのデスクトップとサーバーOSにはデフォルトでインストールされていますが、組み込みLinuxまたは他のUNIXは代わりにシェルユーティリティの代替コレクションを使用する場合があります)。 。
ところで: Busybox を見ると、ls
、ps
およびcat
も組み込みコマンドであることがわかります(または組み込みシステムに使用され、不要なものはすべて除外できます)。
echo
がシェル組み込みである必要がある本当の理由は次のとおりです。
$PASSWORD
にパスワードがあるとします。ファイル./password
にどのように書き込みますか?当然のことながら、ほとんどのプログラマーは次のように記述します。
echo "$PASSWORD" >./password
ただし、echo
が組み込みのシェルでない場合、パスワードはps
情報を介してすべてのユーザーに漏洩します。
もちろん、それについて賢くしたい場合は、echo
なしでパスワードを保存する方法を見つけることができます。おそらく他のいくつかのシェル機能を利用します。
cat >./password <<EOF
${PASSWORD}
EOF
ただし、echo
を組み込みとして持つことは、パスワードをファイルに保存する最も明白な方法も機能するため、重要なシートベルトです。