Ist es möglich, die eingebauten Befehle auf Bash zu beschränken?

12

Inspiriert von dieser Frage mit dem Titel: Wann werden die eingebauten Befehle in den Speicher geladen ? Als ich versuchte, diese zu beantworten, habe ich den folgenden Befehl ausprobiert und war etwas überrascht, dass ich ihn nicht ausführen konnte:

$ strace cd $HOME

Gibt es eine Methode, mit der ich strace für die in Bash integrierten Befehle ausführen kann?

slm
quelle
1
Warum ist es Ihrer Meinung nach überraschend, dass straceein Programm, das nicht ausgeführt wird, nicht zu einer Ablaufverfolgung führt?
Bananguin

Antworten:

14

Wenn Sie darüber nachdenken, wie es stracefunktioniert, ist es absolut sinnvoll, dass keines der in Bash eingebauten Elemente nachvollziehbar ist. stracekann nur aktuelle ausführbare Dateien verfolgen, die eingebauten jedoch nicht.

Zum Beispiel mein cdBefehl:

$ type cd
cd is a function
cd () 
{ 
    builtin cd "$@";
    local result=$?;
    __rvm_project_rvmrc;
    __rvm_after_cd;
    return $result
}

Trick um die CD zu stracen?

Ich bin auf diese Technik gestoßen, stracebei der Sie den tatsächlichen bashProzess aufrufen und auf cddiese Weise indirekt verfolgen können.

Beispiel

$ stty -echo
$ cat | strace bash > /dev/null

Was dazu führt, dass ich den bashProzess wie folgt straffen kann:

....
getegid()                               = 501
getuid()                                = 500
getgid()                                = 501
access("/bin/bash", X_OK)               = 0
stat("/bin/bash", {st_mode=S_IFREG|0755, st_size=940312, ...}) = 0
geteuid()                               = 500
getegid()                               = 501
getuid()                                = 500
getgid()                                = 501
access("/bin/bash", R_OK)               = 0
getpgrp()                               = 32438
rt_sigaction(SIGCHLD, {0x43e360, [], SA_RESTORER, 0x34e7233140}, {SIG_DFL, [], SA_RESTORER, 0x34e7233140}, 8) = 0
getrlimit(RLIMIT_NPROC, {rlim_cur=1024, rlim_max=62265}) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
fcntl(0, F_GETFL)                       = 0 (flags O_RDONLY)
fstat(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, 

Dies ist die Bash-Eingabeaufforderung, in der sie auf Eingaben wartet. Also lass es uns den Befehl geben cd ..:

read(0, "c", 1)                         = 1
read(0, "d", 1)                         = 1
read(0, " ", 1)                         = 1
read(0, ".", 1)                         = 1
read(0, ".", 1)                         = 1
read(0, "\n", 1)                        = 1
stat("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/home/saml", {st_mode=S_IFDIR|0700, st_size=32768, ...}) = 0
stat("/home/saml/tst", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
stat("/home/saml/tst/90609", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
stat("/home/saml/tst/90609", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
chdir("/home/saml/tst")                 = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, 

An der obigen Ausgabe können Sie sehen, wo ich den Befehl eingegeben habe cd ..und die Eingabetaste ( \n) drücken . Von dort aus können Sie sehen, dass die stat()Funktion aufgerufen wurde und dass Bash danach an einer anderen read(0..Eingabeaufforderung sitzt und auf einen anderen Befehl wartet.

slm
quelle
7

Um stracedie Shell zu tun cd /some/dir:

{ strace -p "$$" & sleep 1; cd /some/dir; kill "$!"; }
Stéphane Chazelas
quelle
Warum soll das $1hier denn bashnicht sein %oder %1?
Graeme
1

Sie können Folgendes versuchen:

strace bash -c <command/builtin>

Beispielsweise:

strace bash -c 'cd /path/to/destination/'
Han Solo
quelle