以下のすべてのコマンド(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