Linuxはシェルスクリプトをどのように処理しますか?

Linuxはシェルスクリプトをどのように処理しますか?

この質問については、bashシェルスクリプトを考えてみましょう。ただし、この質問はすべての種類のシェルスクリプトに適用する必要があります。

誰かがシェルスクリプトを実行すると、Linuxはすべてのスクリプトを一度に(メモリに)ロードしますか、それともスクリプトコマンドを1つずつ読みますか?(一行ずつ)?

つまり、シェルスクリプトを実行して実行が完了する前に削除すると、実行は終了しますか、それとも続行されますか?

ベストアンサー1

を使用すると、straceシェルスクリプトの実行時にどのように実行されるかを確認できます。

はい

このシェルスクリプトがあるとしましょう。

$ cat hello_ul.bash 
#!/bin/bash

echo "Hello Unix & Linux!"

次のコマンドを使用して実行しますstrace

$ strace -s 2000 -o strace.log ./hello_ul.bash
Hello Unix & Linux!
$

strace.logファイルの内部を見ると、次のことがわかります。

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

ファイルを読み込むと、次のように実行されます。

...
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)                           = ?

上記では、スクリプト全体が単一のエンティティとして読み込まれ、そこで実行されているように見えることが明らかになります。だからそうだろう「ナタナダ」少なくともBashの場合は、ファイルを読み込んで実行します。それでは、実行中にスクリプトを編集することは可能だと思いますか?

メモ:しかし、そうしないでください!スクリプトファイルの実行を妨げてはいけない理由については、読んでください。

他の通訳者はどうですか?

しかし、あなたの質問に問題があります。 Linuxは必ずしもファイルの内容をロードするわけではなく、コンテンツをロードするのはインタプリタなので、ファイルを完全にロードするのか、一度にチャンクまたは行ずつロードするのかは、インタプリタの実装方法によって異なります。

では、なぜファイルを編集できないのですか?

しかし、より大きなスクリプトを使用すると、上記のテストが少し誤解を招く可能性があることがわかります。実際、ほとんどのインタプリタはファイルをチャンクとしてロードします。これは、ファイルチャンクをロードして処理し、他のチャンクをロードする多くのUnixツールの標準です。しばらく前に、私が書いたU&L Q&Aでこの動作を見ることができますgrepgrep / egrepは毎回どのくらいのテキストを消費しますか?

はい

次のようなシェルスクリプトを書いているとしましょう。

$ ( 
    echo '#!/bin/bash'; 
    for i in {1..100000}; do printf "%s\n" "echo \"$i\""; done 
  ) > ascript.bash;
$ chmod +x ascript.bash

このファイルを生成します。

$ ll ascript.bash 
-rwxrwxr-x. 1 saml saml 1288907 Mar 23 18:59 ascript.bash

これには次の種類のコンテンツが含まれます。

$ head -3 ascript.bash ; echo "..."; tail -3 ascript.bash 
#!/bin/bash
echo "1"
echo "2"
...
echo "99998"
echo "99999"
echo "100000"

ここで上記と同じ手法を使って実行すると、次のようになります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

ファイルは8KB単位で読み取られるため、Bashや他のシェルはファイルを完全にロードせずに代わりにチャンクで読み取ることができます。

引用する

おすすめ記事