Apakah mungkin untuk memindahkan perintah builtin ke Bash?

12

Terinspirasi oleh pertanyaan ini, berjudul: Kapan perintah bawaan dimuat ke memori , ketika mencoba menjawab ini saya mencoba perintah berikut dan sedikit terkejut bahwa saya tidak bisa menjalankannya:

$ strace cd $HOME

Apakah ada metode yang dapat saya gunakan untuk menjalankan strace untuk perintah builtin ke Bash?

slm
sumber
1
Menurut Anda mengapa mengejutkan bahwa stracetidak menjalankan program tidak menghasilkan jejak?
Bananguin

Jawaban:

14

Jika Anda berpikir tentang cara stracekerjanya maka masuk akal jika tidak ada bawaan untuk Bash yang dapat dilacak. stracehanya bisa melacak executable yang sebenarnya, sedangkan yang builtin tidak.

Sebagai contoh, cdperintah saya :

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

Trik untuk strace'ing cd?

Saya menemukan teknik ini di mana Anda bisa meminta proses yang stracesebenarnya bashdan dengan demikian, secara tidak langsung melacaknya cd.

Contoh

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

Yang menghasilkan saya bisa strace bashproses sebagai berikut:

....
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, 

Ini adalah prompt Bash, di mana ia duduk di sana, menunggu beberapa masukan. Jadi mari kita beri perintah 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, 

Dari output di atas, Anda dapat melihat di mana saya mengetik perintah, cd ..dan tekan enter, ( \n). Dari sana Anda dapat melihat bahwa stat()fungsi itu dipanggil, dan setelah itu Bash duduk di read(0..prompt lain , menunggu perintah lain.

slm
sumber
7

Untuk straceshell lakukan cd /some/dir:

{ strace -p "$$" & sleep 1; cd /some/dir; kill "$!"; }
Stéphane Chazelas
sumber
Kenapa di $1sini, untuk bash, seharusnya ini tidak menjadi %atau %1?
Graeme
1

Anda dapat mencoba yang berikut ini:

strace bash -c <command/builtin>

Sebagai contoh:

strace bash -c 'cd /path/to/destination/'
han solo
sumber