Si lo usa strace
, puede ver cómo se ejecuta un script de shell cuando se ejecuta.
Ejemplo
Digamos que tengo este script de shell.
$ cat hello_ul.bash
#!/bin/bash
echo "Hello Unix & Linux!"
Ejecutándolo usando strace
:
$ strace -s 2000 -o strace.log ./hello_ul.bash
Hello Unix & Linux!
$
Echar un vistazo dentro del strace.log
archivo revela lo siguiente.
...
open("./hello_ul.bash", O_RDONLY) = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7fff0b6e3330) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR) = 0
read(3, "#!/bin/bash\n\necho \"Hello Unix & Linux!\"\n", 80) = 40
lseek(3, 0, SEEK_SET) = 0
getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=4*1024}) = 0
fcntl(255, F_GETFD) = -1 EBADF (Bad file descriptor)
dup2(3, 255) = 255
close(3)
...
Una vez que el archivo ha sido leído, se ejecuta:
...
read(255, "#!/bin/bash\n\necho \"Hello Unix & Linux!\"\n", 40) = 40
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc0b38ba000
write(1, "Hello Unix & Linux!\n", 20) = 20
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(255, "", 40) = 0
exit_group(0) = ?
En lo anterior, podemos ver claramente que todo el script parece estar siendo leído como una sola entidad y luego ejecutado allí. Por lo tanto, "aparecerá" al menos en el caso de Bash en el que lee el archivo y luego lo ejecuta. ¿Crees que podrías editar el script mientras se está ejecutando?
NOTA: ¡no lo hagas! Siga leyendo para comprender por qué no debe meterse con un archivo de script en ejecución.
¿Qué pasa con otros intérpretes?
Pero tu pregunta está un poco fuera de lugar. No es Linux el que necesariamente carga el contenido del archivo, es el intérprete el que carga el contenido, por lo que depende realmente de cómo el intérprete implemente si carga el archivo por completo o en bloques o líneas a la vez.
Entonces, ¿por qué no podemos editar el archivo?
Sin embargo, si usa un script mucho más grande, notará que la prueba anterior es un poco engañosa. De hecho, la mayoría de los intérpretes cargan sus archivos en bloques. Esto es bastante estándar con muchas de las herramientas de Unix donde cargan bloques de un archivo, lo procesan y luego cargan otro bloque. Puede ver este comportamiento con estas preguntas y respuestas de U&L que escribí hace un tiempo sobre grep
, tituladas: ¿Cuánto texto consume grep / egrep cada vez? .
Ejemplo
Digamos que hacemos el siguiente script de shell.
$ (
echo '#!/bin/bash';
for i in {1..100000}; do printf "%s\n" "echo \"$i\""; done
) > ascript.bash;
$ chmod +x ascript.bash
Resultando en este archivo:
$ ll ascript.bash
-rwxrwxr-x. 1 saml saml 1288907 Mar 23 18:59 ascript.bash
Que contiene el siguiente tipo de contenido:
$ head -3 ascript.bash ; echo "..."; tail -3 ascript.bash
#!/bin/bash
echo "1"
echo "2"
...
echo "99998"
echo "99999"
echo "100000"
Ahora, cuando ejecute esto utilizando la misma técnica anterior con strace
:
$ strace -s 2000 -o strace_ascript.log ./ascript.bash
...
read(255, "#!/bin/bash\necho \"1\"\necho \"2\"\necho \"3\"\necho \"4\"\necho \"5\"\necho \"6\"\necho \"7\"\necho \"8\"\necho \"9\"\necho \"10\"\necho
...
...
\"181\"\necho \"182\"\necho \"183\"\necho \"184\"\necho \"185\"\necho \"186\"\necho \"187\"\necho \"188\"\necho \"189\"\necho \"190\"\necho \""..., 8192) = 8192
Notarás que el archivo se está leyendo en incrementos de 8 KB, por lo que Bash y otros shells probablemente no cargarán un archivo en su totalidad, sino que los leerán en bloques.
Referencias