Аналогичный скрипт sudo
, но без схожих результатов:
$ cat script.sh
#!/bin/bash
sed -e 's/^/--/'
whoami
$ bash < script.sh
--whoami
$ dash < script.sh
itvirta
С bash
, остальная часть сценария идет как ввод sed
, с dash
, оболочка интерпретирует его.
Работает strace
на них: dash
читает блок скрипта (здесь восемь кБ, более чем достаточно для хранения всего скрипта), а затем порождает 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|...
Это означает, что дескриптор файла находится в конце файла и sed
не будет видеть никаких входных данных. Оставшаяся часть буферизуется внутри dash
. (Если длина скрипта превышает размер блока 8 кБ, оставшаяся часть будет прочитана sed
.)
Bash, с другой стороны, ищет конец последней команды:
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|...
Если вход поступает из трубы, как здесь:
$ cat script.sh | bash
перематывать нельзя, так как трубы и розетки не доступны. В этом случае Bash возвращается к чтению ввода по одному символу за раз, чтобы избежать перечитывания. ( fd_to_buffered_stream()
вinput.c
) Выполнение полного системного вызова для каждого байта в принципе не очень эффективно. На практике, я не думаю, что чтения будут большими затратами по сравнению, например, с тем фактом, что большинство вещей, которые делает оболочка, порождает совершенно новые процессы.
Похожая ситуация такая:
echo -e 'foo\nbar\ndoo' | bash -c 'read a; head -1'
Подоболочка должна быть уверена, что read
читает только первую новую head
строку , чтобы видеть следующую строку. (Это dash
тоже работает .)
Другими словами, Bash идет на дополнительные длины, чтобы поддерживать чтение одного и того же источника как для самого скрипта, так и для команд, выполняемых из него. dash
не делает. Пакет zsh
и ksh93
в Debian идут вместе с Bash.
sudo su
: unix.stackexchange.com/questions/218169/…