1. 概要

Linuxには、いくつかの簡単なコマンドがあります。 通常、コマンドの機能はわかっています。 ただし、さらに一歩進んでみると、これらのコマンドの使用例がわからない場合があります。

/ bin /trueおよび/bin /falseコマンドは2つの例です。

このチュートリアルでは、これら2つの非常に単純なコマンドを詳しく見ていきましょう。

2. / bin /trueおよび/bin /falseの概要

/ bin /true/bin /falseはどちらもCoreutilパッケージのメンバーであり、ほとんどすべてのLinuxディストリビューションで利用できます。 一部のディストリビューションでは、/binではなく/usr/binの下にコマンドがインストールされる場合があることに注意してください。

2つのコマンドのマニュアルページを見ると、説明は非常に単純です。

  • / bin / true –「何もしないで正常に」
  • / bin / false –「何もしない、失敗する」

コマンドを実行すると、 / bin / trueコマンドが0を返し、/ bin /falseコマンドが1を返すことを除いて、実際には「何もしません」。

$ /bin/false
$ echo $?
0

$ /bin/false
$ echo $?
1

さて、2つの簡単なコマンドを学びました。 しかし、彼らは何もしないので、なぜ2つのコマンドが必要なのかと尋ねるかもしれません。 それらのユースケースは何ですか?

次に、 / bin /trueおよび/bin /falseコマンドを使用した実際の例をいくつか見てみましょう。

3. / bin /falseの使用例

まず、 / bin /falseコマンドを見てみましょう。

/ bin /falseコマンドは失敗コードを返すだけであることがわかりました。 その最も一般的な使用法は、特定のユーザーアカウントへのシェルアクセスを拒否することです

次に、このマシンのどのユーザーのシェルが / bin /falseに設定されているかを確認しましょう。

$ grep 'false' /etc/passwd
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
mail:x:8:12:mail:/var/spool/mail:/bin/false
ftp:x:14:11:ftp:/srv/ftp:/bin/false
http:x:33:33:http:/srv/http:/bin/false
nobody:x:99:99:nobody:/:/bin/false
rtkit:x:133:133:RealtimeKit:/proc:/bin/false
ntp:x:87:87:Network Time Protocol:/var/lib/ntp:/bin/false

上記のリストのユーザーがシェルを介してログインしようとすると、 / bin /falseは1を返します。 つまり、ユーザーのシェルアクセスを拒否します。

ここで、テストする例としてユーザーnobodyを取り上げましょう。

root# su nobody
root# echo $?
1

ユーザーnobodyのパスワードがわからないため、 root userとしてログインし、nobodyユーザーに変更しようとします。

上記の出力が示すように、「 su nobody」コマンドを実行した後も、現在のユーザーはrootのままです。 また、「sunobody」コマンドが戻りコード1で失敗しました。

つまり、「ユーザーの切り替え」操作が失敗しました。

次に、 / bin /trueの使用例をいくつか見てみましょう。

4. / bin /trueを使用して無限ループを構築する

/ bin / true コマンドは常に0を返すため、これを使用して無限ループを記述できます。

while /bin/true
do
   some-operations
   ...
   # We need to break out of the loop, otherwise the script will hang.
done

5. 操作を常に成功させる

コマンドの実行でゼロ以外のリターンコードが返される場合、/ bin/trueコマンドを使用するととにかく成功として扱うことができます

まあ、それは少し奇妙に聞こえます。 次に、例を見てみましょう。 シナリオをすばやく説明できる場合があります。

5.1. executer.shスクリプト

まず、簡単なシェルスクリプトを見てみましょう。

$ cat executor.sh
#!/bin/bash

#Arguments
OPERATION="$1"
INPUT="$2"

execute() {
    echo "Start executing operation: [$1]"
    $1 && echo "Success! Logging status in the Execution-Database ..." \
        || echo "Failed! Logging and sending alert messages ..."
}

# predefined operations
findErrors() {
    grep -i 'error' "$INPUT"
}

# other opertions...

execute "$OPERATION"

上記のコードが示すように、 executer.sh スクリプトを使用すると、入力を使用して事前定義された操作を実行できます。 この例では、 1つの操作(findErrors )のみを定義しました。

executor 関数は、指定された操作を実行し、実行ステータスのログ記録、エラー処理、場合によってはその他の多くの一般的な作業を後で実行する役割を果たします。

簡単にするために、スクリプトで引数の検証をスキップしたことは言及する価値があります。

5.2. 2つの入力ファイルでfindErrorsを実行する

2つのログファイルがあるとしましょう。

$ head *.log
==> log1.log <==
2021-11-22 11:23:22 [INFO] application starts successfully
2021-11-22 11:24:22 [INFO] clean-up job starts..
2021-11-22 11:24:52 [INFO] clean-up job done!

==> log2.log <==
2021-11-28 18:23:00 [ERROR] IO: File "foo/bar" not found!
2021-11-28 18:24:00 [INFO] User has changed profile.
2021-11-28 18:25:00 [ERROR] DB: Cannot exec SQL Statement "insert into ..."

まず、log2.logファイルに対してfindErrors操作を実行してみましょう。

$ ./executor.sh findErrors log2.log
Start executing operation: [findErrors]
2021-11-28 18:23:00 [ERROR] IO: File "foo/bar" not found!
2021-11-28 18:25:00 [ERROR] DB: Cannot exec SQL Statement "insert into ..."
Success! Logging status in the Execution-Database ...

上記の出力は、エグゼキュータがfindErrors操作を正常に実行したことを示しています。

次に、他のログファイルでも同じことをしましょう。

$ ./executor.sh findErrors log1.log
Start executing operation: [findErrors]
Failed! Logging and sending alert messages ...

今回、エグゼキュータは操作が失敗したことを報告し、プログラムはエラー処理プロセスに入ります。

これは、log1.logファイルに「ERROR」エントリが含まれていないためです。 したがって、 grepが結果を検出しない場合、grepコマンドは0ではなくコード1を返します。

したがって、エグゼキュータがリターンコード1を受け取った場合、操作は失敗したと見なされます。

実際、これは私たちが本当に望んでいることではありません。 findErrors 操作で一致するものが見つからなくても、操作は成功するはずです。

それでは、それを修正する方法を見てみましょう。

5.3. 問題の解決

それでは、 / bin /trueコマンドを使用して修正してみましょう。

#!/bin/bash
...
 
findErrors() {
    grep -i 'error' "$INPUT"; /bin/true
}

...

grepコマンドの後にセミコロンを付けて連結/ bin /trueコマンドを実行できます。 このように、 grepが入力で一致を検出したかどうかに関係なく、findErrors操作に常に0を返すように要求します

findErrors操作をlog1.logファイルでもう一度テストしてみましょう。

$ ./executor.sh findErrors log1.log
Start executing operation: [findErrors]
Success! Logging status in the Execution-Database ...

ご覧のとおり、「 ERROR 」はまだ見つかりませんが、操作は成功します。

これで、プログラムは期待どおりに実行されます。

6. シェルビルトインとCoreutilsパッケージ

6.1. シェルビルトインtrueおよびfalse

例を通して、 / bin /trueおよび/bin /falseコマンドを学習しました。

/ binは通常$PATHシステム変数にありますが、これまでtrueの代わりに/bin /trueを使用していることに鋭い目で気付いたかもしれません。 。

これは、Coreutilsの / bin /true/bin /falseにLinux上の兄弟がいるためです。 それらの兄弟は、シェルに組み込まれているtrueおよびfalseコマンドです。

type -a コマンドを使用して、それらを一覧表示できます。次に例を示します。

$ type -a true
true is a shell builtin
true is /bin/true

したがって、上記の出力でわかるように、このシステムには2つのtrueコマンドがあります。 1つはシェル(Bash)組み込みコマンドで、もう1つはCoreutilsパッケージの / bin /trueコマンドです。

チュートリアルのこの部分では、Coreutilsパッケージのtrueおよびfalseコマンドに焦点を当てます。 したがって、前のセクションでは、 / bin /trueまたは/bin /falseを使用します。

シェルでtrueを実行するだけの場合、シェルに組み込まれているtrueを実行します。

組み込みのtrueおよびfalseは、対応するCoreutilsコマンドと同じ機能を備えています。

6.2. バッシュビルトインtrue対。 / bin / true

truefalseは基本的に何もしないことを学びました。 言い換えれば、それらは非常に高速である必要があります。

次に、興味深いテストを行いましょう。Bashの組み込みtrueとCoreutilstrueのベンチマークです。

trueコマンドを10,000回実行し、timeコマンドを使用して実行にかかる時間を測定します。

まず、組み込みのBash trueを測定しましょう。

$ time for i in {1..10000}; do true; done

real	0m0.015s
user	0m0.015s
sys	0m0.000s

あっという間に終わりました! 次に、 / bin /trueコマンドをテストしてみましょう。

$ time for i in {1..10000}; do /bin/true; done

real	0m12.552s
user	0m10.863s
sys	0m10.013s

今回は、出力が表示されるまで約13秒待ちました。

したがって、組み込みのBash trueは、Coreutilsバージョンよりもはるかに高速です。

たとえば、このマシンでは、組み込みのBash true は、Coreutilsバージョンよりも約836(12.552 / 0.015)倍高速です。 驚いた!

6.3. Coreutilsパッケージから/bin /true/bin / false が必要なのはなぜですか?

Bashの組み込みtruefalseおよびCoreutilsバージョンが同じ機能を持っていることを学びました。 さらに、組み込みのシェルコマンドはCoreutilsバージョンよりもはるかに高速です。

次に、なぜ外部コマンド / bin /true/bin /falseがまだ必要なのかと尋ねる場合があります。

答えは、組み込みのシェルコマンドがシェルにのみ存在するためです。 したがって、シェルから呼び出す場合にのみ使用できます。

前の例では、 / etc /passwdファイルで/bin / false を使用して、ユーザーがシェルにアクセスできないようにする方法を示しました。 これは、シェルからではなく / bin /falseを呼び出す良い例でもあります。

それでは、ユーザーguestのシェルをfalseに変更して、guestに切り替えたときに何が起こるかを見てみましょう。

$ grep '^guest' /etc/passwd
guest:x:1001:1001::/home/guest:false
$ su guest
Password: 
su: failed to execute false: No such file or directory

上記の出力は、ファイルまたはディレクトリ「 false」が見つからないため、suコマンドが失敗したことを示しています。 これは、 false コマンドを呼び出すが、シェルからは呼び出さないためです。

したがって、この時点では、すべての組み込みシェルコマンドを使用できません。

7. 結論

この記事では、 / bin /true/bin /falseの2つの簡単なコマンドを学習しました。

さらに、シェルに組み込まれているtrueおよびfalseとCoreutilsバージョンの違いについても説明しました。