¿Es posible distribuir los comandos incorporados a Bash?

13

Inspirado por esta pregunta, titulada: ¿ Cuándo se cargan los comandos integrados en la memoria? Al intentar responder esto, probé el siguiente comando y me sorprendió un poco que no pudiera ejecutarlo:

$ strace cd $HOME

¿Hay algún método que pueda usar para ejecutar strace para los comandos incorporados a Bash?

slm
fuente
1
¿Por qué crees que es sorprendente que el hecho stracede no ejecutar un programa no dé como resultado un rastro?
Bananguin

Respuestas:

15

Si piensas en cómo stracefunciona, tiene mucho sentido que ninguno de los componentes de Bash sea rastreable. stracesolo puede rastrear ejecutables reales, mientras que los incorporados no lo son.

Por ejemplo, mi cdcomando:

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

Truco para strace'ing cd?

Encontré esta técnica en la que puedes invocar straceel bashproceso real y, al hacerlo, rastrear indirectamente de cdesa manera.

Ejemplo

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

Lo que resulta en que yo pueda ordenar el bashproceso de la siguiente manera:

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

Este es el indicador de Bash, donde está sentado allí, esperando alguna entrada. Entonces, demos el comando 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, 

En el resultado anterior, puede ver dónde escribí el comando cd ..y presione enter, ( \n). Desde allí, puede ver que stat()se llamó a la función y que luego Bash está sentado en otro read(0..indicador, esperando otro comando.

slm
fuente
7

A stracela cáscara haciendo cd /some/dir:

{ strace -p "$$" & sleep 1; cd /some/dir; kill "$!"; }
Stéphane Chazelas
fuente
¿Por qué el $1aquí, para bash, esto no debería ser %o %1?
Graeme
1

Puedes probar lo siguiente:

strace bash -c <command/builtin>

Por ejemplo:

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