web-dev-qa-db-ja.com

シェルビルトインコマンドをエコーするのはなぜですか?

$ which echo
echo: Shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

Echoがlspscatなどの独立したユーティリティではないのはなぜですか?なぜシェル固有なのですか?何か良い理由はありますか?

35
Lazer

ビルトインには2つのクラスがあります。

  1. 一部のコマンドは、外部にあると機能しないため、シェルプログラム自体に組み込む必要があります。

    cdは、外部の場合、独自のディレクトリしか変更できないため、その1つです。シェルの現在の作業ディレクトリには影響しません。 (参照: cdがプログラムではない理由

  2. 他のクラスのコマンドは、純粋に効率のためにシェルに組み込まれています。

    dashman page には、このクラスのコマンドの例としてprintfecho、およびtestについて言及している組み込みのセクションがあります。

Unixシステムには、常にその2番目のクラスのコマンド用の個別の実行可能ファイルが含まれています。これらの個別の実行可能ファイルは、使用する可能性のあるすべてのシェルにも組み込まれていますが、私が使用したすべてのUnixyシステムで引き続き使用できます。 ( [〜#〜] posix [〜#〜] 実際には、これらの実行可能ファイルが存在する必要があります。)

echoがAT&T Unix System V Release 3.1のシェルに組み込まれたと思います。 AT&Tのマニュアルの2つの異なるエディションの比較に基づいています B1シリーズUnixシステム 。誰かが親切にこれらのマニュアルの1986年版をスキャンし、 それらをオンラインに置く ;これらはSVR3のオリジナルリリースに対応しています。 echoNIX System Vユーザーズマニュアル、ボリュームII の523ページのリストにないことがわかります。コマンドが組み込まれている場合は、シェル。私の地元の1987年のSVR3.1マニュアルの紙のコピーでは、echoisがマニュアルのこのセクションにリストされています。

これはバークレーではないと確信しています [〜#〜] 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..
*/      
72
Warren Young

一部のコマンドが組み込まれている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
19
bhm

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ビルトインを使用しているようです。しかし、スクリプトは依然としてどこでも問題なく動作するため、問題はないようです。

13

Bhmの答えを補足するために、/binPATHから誤って削除されました。 echo $PATHそれを見つけるためですよね?

6

現在、ほとんどのシェルには組み込みのechoが含まれていますが、GNU CoreUtilsにはスタンドアロンの実装も含まれています。

$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo

GNU Coreutilsがインストールされていないようです(ほとんどのLinuxベースのデスクトップとサーバーOSにはデフォルトでインストールされていますが、組み込みLinuxまたは他のUNIXは代わりにシェルユーティリティの代替コレクションを使用する場合があります)。 。

ところで: Busybox を見ると、lspsおよびcatも組み込みコマンドであることがわかります(または組み込みシステムに使用され、不要なものはすべて除外できます)。

2
JanC

echoがシェル組み込みである必要がある本当の理由は次のとおりです。

$PASSWORDにパスワードがあるとします。ファイル./passwordにどのように書き込みますか?当然のことながら、ほとんどのプログラマーは次のように記述します。

echo "$PASSWORD" >./password

ただし、echoが組み込みのシェルでない場合、パスワードはps情報を介してすべてのユーザーに漏洩します。

もちろん、それについて賢くしたい場合は、echoなしでパスワードを保存する方法を見つけることができます。おそらく他のいくつかのシェル機能を利用します。

cat >./password <<EOF
${PASSWORD}
EOF

ただし、echoを組み込みとして持つことは、パスワードをファイルに保存する最も明白な方法も機能するため、重要なシートベルトです。

1
DepressedDaniel