Jeśli używasz strace
, możesz zobaczyć, w jaki sposób skrypt powłoki jest wykonywany podczas jego uruchamiania.
Przykład
Powiedz, że mam ten skrypt powłoki.
$ cat hello_ul.bash
#!/bin/bash
echo "Hello Unix & Linux!"
Uruchamianie za pomocą strace
:
$ strace -s 2000 -o strace.log ./hello_ul.bash
Hello Unix & Linux!
$
Przejrzenie strace.log
pliku ujawnia następujące informacje.
...
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)
...
Po odczytaniu plik jest następnie wykonywany:
...
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) = ?
Powyżej widać wyraźnie, że cały skrypt wydaje się być wczytywany jako pojedyncza jednostka, a następnie wykonywany po nim. Tak więc „pojawi się” przynajmniej w przypadku Basha, że wczyta plik, a następnie go wykona. Myślisz, że możesz edytować skrypt podczas jego działania?
UWAGA: Nie rób tego! Czytaj dalej, aby zrozumieć, dlaczego nie powinieneś zadzierać z uruchomionym plikiem skryptu.
Co z innymi tłumaczami?
Ale twoje pytanie jest nieco wyłączone. To nie Linux ładuje zawartość pliku, to interpreter ładuje zawartość, więc tak naprawdę to zależy od tego, jak interpreter zaimplementuje to, czy ładuje plik w całości, czy w blokach lub liniach na raz.
Dlaczego więc nie możemy edytować pliku?
Jeśli używasz znacznie większego skryptu, zauważysz jednak, że powyższy test jest nieco mylący. W rzeczywistości większość tłumaczy ładuje swoje pliki w blokach. Jest to dość standardowe w przypadku wielu narzędzi uniksowych, w których ładują bloki pliku, przetwarzają go, a następnie ładują kolejny blok. Możesz zobaczyć to zachowanie z tymi pytaniami i pytaniami U&L, które napisałem przed chwilą grep
, zatytułowane: Ile tekstu zużywa grep / egrep za każdym razem? .
Przykład
Załóżmy, że wykonujemy następujący skrypt powłoki.
$ (
echo '#!/bin/bash';
for i in {1..100000}; do printf "%s\n" "echo \"$i\""; done
) > ascript.bash;
$ chmod +x ascript.bash
Wynikające z tego pliku:
$ ll ascript.bash
-rwxrwxr-x. 1 saml saml 1288907 Mar 23 18:59 ascript.bash
Który zawiera następujący typ treści:
$ head -3 ascript.bash ; echo "..."; tail -3 ascript.bash
#!/bin/bash
echo "1"
echo "2"
...
echo "99998"
echo "99999"
echo "100000"
Teraz, gdy uruchomisz to przy użyciu tej samej techniki powyżej z 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
Zauważysz, że plik jest wczytywany z przyrostem 8 KB, więc Bash i inne powłoki prawdopodobnie nie załadują pliku w całości, a raczej czytają je w blokach.
Referencje