GNU/Linux >> Linux の 問題 >  >> Linux

ヒアドキュメントの親シェルがダッシュのサブコマンドでは機能しないのに、Bashは機能するのはなぜですか?

以下のすべてのコマンド(dash)でDebianストレッチを実行しています およびbash )はbashに入力されます。
whoami ユーザーテストとして実行されることはないようです 以下のコードのようにダッシュで。

$ sudo dash << 'end'
> su test
> whoami
> end
root
$ sudo bash << 'end'
> su test
> whoami
> end
test

承認された回答:

代わりに次の例を検討してください:

$ cat f
grep pos /proc/self/fdinfo/0
IFS= read -r var
echo A
echo B
printf '%s\n' "var=$var"
$ bash < f
pos:    29
B
var=echo A
$ dash < f
pos:    85
A
B
var=

ご覧のとおり、その時点でgrep コマンドが実行されると、stdin内の位置は、dashを使用してファイルの最後になります。 、およびgrepに続く改行の直後 bashのコマンド 。

echo A コマンドはdashによって実行されます ただし、bashの場合 、readへの入力としてフィードされます 。

何が起こったのかというと、そのdash bashを実行しながら、入力全体(実際にはテキストのブロック)を読み取ります コマンドを実行する前に、一度に1行ずつ読んでください。

これを行うには、bash 改行を超えて読み取られないように、一度に1バイトを読み取る必要がありますが、入力が通常のファイルの場合(fの場合など) 上記のファイルだけでなく、ヒアドキュメント-dashで、bashが一時ファイルとして実装するドキュメント パイプを使用)、bash ブロックごとに読み取り、行の終わりに戻ってシークすることで最適化します。これは、straceで確認できます。 Linuxの場合:

$ strace -e read,lseek bash < f
[...]
lseek(0, 0, SEEK_CUR)                   = 0
read(0, "grep pos /proc/self/fdinfo/0\nIFS"..., 85) = 85
lseek(0, -56, SEEK_CUR)                 = 29
pos:    29
[...]

$ strace -e read,lseek dash < f
read(0, "grep pos /proc/self/fdinfo/0\nIFS"..., 8192) = 85
pos:    85
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12422, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
read(0, "", 1)                          = 0
[...]

stdinが端末デバイスの場合、各read() 端末から送信された行を返すため、通常、bashでも同様の動作が見られます。 およびdash

あなたの場合、あなたは次のことができます:

sudo dash << 'end-of-script'
su test <<"end"
whoami
end
end-of-script

以上:

sudo sh -c '
  su test -c whoami
'

またはさらに良い:

sudo -u test whoami

Linux
  1. Bashシェルのカスタマイズ

  2. 正規表現がXで機能するのに、Yでは機能しないのはなぜですか?

  3. 〜/ .bash_profileが機能しないのはなぜですか?

  1. .bashrcの目的とそれはどのように機能しますか?

  2. 子プロセスのPgidが親のPidではないのはなぜですか?

  3. 一部のコマンドでBashプロセス置換が機能しないのはなぜですか?

  1. Bashシェル関数での循環名参照、ただしKshではない?

  2. Bash翻訳ファイルにすべてのエラーテキストが含まれていないのはなぜですか?

  3. Linux –ロケールEs_mxは機能するがEsは機能しないのはなぜですか?