Script yang serupa, tanpa sudo
, tetapi hasil yang serupa:
$ cat script.sh
#!/bin/bash
sed -e 's/^/--/'
whoami
$ bash < script.sh
--whoami
$ dash < script.sh
itvirta
Dengan bash
, sisa skrip berjalan sebagai input untuk sed
, dengan dash
, shell mengartikannya.
Menjalankannya strace
: dash
membaca satu blok skrip (delapan kB di sini, lebih dari cukup untuk menampung seluruh skrip), dan kemudian memunculkan sed
:
read(0, "#!/bin/bash\nsed -e 's/^/--/'\nwho"..., 8192) = 36
stat("/bin/sed", {st_mode=S_IFREG|0755, st_size=73416, ...}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|...
Yang berarti filehandle ada di akhir file, dan sed
tidak akan melihat input apa pun. Bagian yang tersisa sedang disangga di dalam dash
. (Jika skrip lebih panjang dari ukuran blok 8 kB, bagian yang tersisa akan dibaca oleh sed
.)
Bash, di sisi lain, mencari kembali ke akhir perintah terakhir:
read(0, "#!/bin/bash\nsed -e 's/^/--/'\nwho"..., 36) = 36
stat("/bin/sed", {st_mode=S_IFREG|0755, st_size=73416, ...}) = 0
...
lseek(0, -7, SEEK_CUR) = 29
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|...
Jika input berasal dari pipa, seperti di sini:
$ cat script.sh | bash
rewinding tidak dapat dilakukan, karena pipa dan soket tidak dapat dicari. Dalam hal ini, Bash kembali membaca input karakter satu per satu untuk menghindari overreading. ( fd_to_buffered_stream()
dalaminput.c
) Melakukan panggilan sistem penuh untuk setiap byte pada prinsipnya tidak terlalu efektif. Dalam praktiknya, saya tidak berpikir bacaan akan menjadi biaya overhead yang besar dibandingkan misalnya fakta bahwa sebagian besar hal shell melibatkan pemijahan seluruh proses baru.
Situasi serupa adalah ini:
echo -e 'foo\nbar\ndoo' | bash -c 'read a; head -1'
Subshell harus memastikan read
hanya membaca baris baru pertama, sehingga head
melihat baris berikutnya. (Ini juga berfungsi dengan baik dash
.)
Dengan kata lain, Bash berusaha lebih keras untuk mendukung membaca sumber yang sama untuk skrip itu sendiri, dan untuk perintah yang dijalankan darinya. dash
tidak. Itu zsh
, dan ksh93
dikemas dalam Debian pergi dengan Bash pada ini.
sudo su
: unix.stackexchange.com/questions/218169/…