[LINUX] Bis die Shell den Befehl findet

Überblick

Mal sehen, wie bash nach Befehlen gemäß der Umgebungsvariablen PATH sucht.

yoichinakayama@penguin:~$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/home/yoichinakayama/.local/bin
yoichinakayama@penguin:~$ type hostname
hostname is /bin/hostname
yoichinakayama@penguin:~$ hostname
penguin

Wie auch immer, strace

strace

yoichinakayama@penguin:~$ strace hostname 2>&1 |head -1
execve("/bin/hostname", ["hostname"], 0x7fe429adf0 /* 31 vars */) = 0

Und Sie können sehen, dass / bin / hostname ausgeführt wird, aber Sie können nur den Trace sehen, von dem aus er ausgeführt wurde, und Sie können nicht sehen, dass er nach einem Befehl sucht.

Bash verfolgen

yoichinakayama@penguin:~$ bash -c "hostname"
penguin

Wenn Sie bash starten und dann ausführen und die gestartete bash verfolgen, können Sie sehen, wie sie für den Befehl aussieht.

yoichinakayama@penguin:~$ strace -f bash -c "hostname" 2>&1 |grep "\(execve\|fstatat\)"
...
newfstatat(AT_FDCWD, "/usr/local/bin/hostname", 0x7ff2d34128, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/hostname", 0x7ff2d34128, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
...
execve("/bin/hostname", ["hostname"], 0x31c1b008 /* 31 vars */) = 0

Entsprechend dem Wert der Umgebungsvariablen PATH [^ 1]

[^ 1]: Der Wert war "/ usr / local / bin: / usr / bin: / bin: / usr / local / games: / usr / games: / home / yoichinakayama / .local / bin"

Sie können sehen, dass Sie das, was Sie finden, ausführen, indem Sie nacheinander suchen, bis Sie es finden.

Wenn nicht gefunden

Wenn Sie einen Befehl angeben, der nicht vorhanden ist

yoichinakayama@penguin:~$ bash -c "hoge"
bash: hoge: command not found

Wird zu einem Fehler führen. in diesem Fall

yoichinakayama@penguin:~$ strace bash -c "hoge" 2>&1 |grep fstatat| grep hoge
newfstatat(AT_FDCWD, "/usr/local/bin/hoge", 0x7ff32941e8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/hoge", 0x7ff32941e8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/bin/hoge", 0x7ff32941e8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/local/games/hoge", 0x7ff32941e8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/games/hoge", 0x7ff32941e8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/home/yoichinakayama/.local/bin/hoge", 0x7ff32941e8, 0) = -1 ENOENT (No such file or directory)

Nach der Suche nach der Umgebungsvariablen PATH wird eine Fehlermeldung ausgegeben.

yoichinakayama@penguin:~$ strace bash -c "hoge" 2>&1 |grep "command not found"
write(2, "bash: hoge: command not found\n", 30bash: hoge: command not found

Suchst du jedes Mal danach?

bash speichert den Pfad des ausgeführten Befehls zwischen.

yoichinakayama@penguin:~$ type hostname
hostname is /bin/hostname
yoichinakayama@penguin:~$ hostname
penguin
yoichinakayama@penguin:~$ type hostname
hostname is hashed (/bin/hostname)
yoichinakayama@penguin:~$ hostname
penguin

Sehen wir uns auch dieses Verhalten an.

yoichinakayama@penguin:~$ strace -f bash -c "hostname; hostname" 2>&1 |grep "\(execve\|fstatat\)"
...
newfstatat(AT_FDCWD, "/usr/local/bin/hostname", 0x7febd16b68, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/hostname", 0x7febd16b68, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
[pid  2555] execve("/bin/hostname", ["hostname"], 0xc2b9008 /* 31 vars */) = 0
[pid  2556] execve("/bin/hostname", ["hostname"], 0xc2b9008 /* 31 vars */) = 0

Sie können sehen, dass es beim zweiten Mal ohne Suche ausgeführt wird.

Cache leeren

Sie können sehen, dass Sie es wieder finden können, indem Sie "hash -r" ausführen.

yoichinakayama@penguin:~$ strace -f bash -c "hostname; hash -r; hostname" 2>&1 |grep "\(execve\|fstatat\)"
...
newfstatat(AT_FDCWD, "/usr/local/bin/hostname", 0x7fc0d8aa08, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/hostname", 0x7fc0d8aa08, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
...
[pid  2598] execve("/bin/hostname", ["hostname"], 0x110de008 /* 31 vars */) = 0
...
newfstatat(AT_FDCWD, "/usr/local/bin/hostname", 0x7fc0d8aba8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/hostname", 0x7fc0d8aba8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/bin/hostname", {st_mode=S_IFREG|0755, st_size=18440, ...}, 0) = 0
...
[pid  2599] execve("/bin/hostname", ["hostname"], 0x110de008 /* 31 vars */) = 0

Geben Sie mit einem absoluten Pfad an

Wenn Sie den Befehl mit einem absoluten Pfad angeben, wird der Befehl ausgeführt, ohne entlang des Pfads zu suchen.

yoichinakayama@penguin:~$ strace -f bash -c "/bin/hostname" 2>&1 |grep "\(execve\|fstatat\)"
execve("/bin/bash", ["bash", "-c", "/bin/hostname"], 0x7fec75a6c8 /* 31 vars */) = 0
newfstatat(AT_FDCWD, "/home/yoichinakayama", {st_mode=S_IFDIR|0755, st_size=622, ...}, 0) = 0
newfstatat(AT_FDCWD, ".", {st_mode=S_IFDIR|0755, st_size=622, ...}, 0) = 0
newfstatat(AT_FDCWD, "/home", {st_mode=S_IFDIR|0755, st_size=28, ...}, 0) = 0
newfstatat(AT_FDCWD, "/home/yoichinakayama", {st_mode=S_IFDIR|0755, st_size=622, ...}, 0) = 0
newfstatat(AT_FDCWD, ".", {st_mode=S_IFDIR|0755, st_size=622, ...}, 0) = 0
newfstatat(AT_FDCWD, "/usr/local/bin/bash", 0x7fff5c3fd8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/usr/bin/bash", 0x7fff5c3fd8, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/bin/bash", {st_mode=S_IFREG|0755, st_size=1016024, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/bash", {st_mode=S_IFREG|0755, st_size=1016024, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/bash", {st_mode=S_IFREG|0755, st_size=1016024, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/bash", {st_mode=S_IFREG|0755, st_size=1016024, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/bash", {st_mode=S_IFREG|0755, st_size=1016024, ...}, 0) = 0
newfstatat(AT_FDCWD, "/bin/bash", {st_mode=S_IFREG|0755, st_size=1016024, ...}, 0) = 0
execve("/bin/hostname", ["/bin/hostname"], 0x3d55e008 /* 31 vars */) = 0

Bestätigungsumgebung

Ich habe es auf dem Terminal des Chromebooks überprüft.

yoichinakayama@penguin:~$ uname -a
Linux penguin 5.4.39-04075-gfc7cb60d7f13 #1 SMP PREEMPT Sun May 10 10:47:48 PDT 2020 aarch64 GNU/Linux
yoichinakayama@penguin:~$ bash --version
GNU bash, version 4.4.12(1)-release (aarch64-unknown-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Recommended Posts

Bis die Shell den Befehl findet
die Shell-Überprüfung
Befehl im Shell-Skript ersetzen
Über den Servicebefehl
Installieren Sie den Befehl pip
Bis die wahrscheinlichste Schätzmethode den wahren Parameter findet
Klonen Sie mit dem Befehl dd
Beschleunigen Sie den Befehl netstat
Überprüfen Sie die Antwort des HTTP-Statuscodes mit dem Befehl curl (#Linux #Shell).
Tauche ein in den Django Custom Befehl [1]
Führen Sie den Shell-Befehl / Python in R aus
Im Python-Befehl zeigt Python auf Python3.8
Erstellen Sie die standardmäßige interaktive Shell IPython
Befehl [linux] kill, um den Prozess abzubrechen
Lassen Sie Python die Befehlsausgabe lesen
Drücken Sie den obersten Befehl mit htop
Shell-Skript numerische Berechnung bc Befehl
Befehl für das aktuelle Verzeichnis Python
Ich möchte einen beliebigen Befehl im Befehlsverlauf von Shell belassen