GNU/Linux >> Belajar Linux >  >> Linux

Mengapa Dokumen Induk Shell Di Sini Tidak Berfungsi Untuk Sub-perintah Di Dash Tapi Bash Bekerja?

Saya menjalankan debian stretch, semua perintah di bawah ini (dash dan bash ) dimasukkan ke bash.
whoami sepertinya tidak pernah dijalankan sebagai pengguna test dalam tanda hubung seperti pada kode di bawah ini.

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

Jawaban yang Diterima:

Pertimbangkan contoh ini sebagai gantinya:

$ 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=

Seperti yang Anda lihat, pada saat grep perintah dijalankan, posisi dalam stdin berada di akhir file dengan dash , dan tepat setelah baris baru yang mengikuti grep perintah di bash .

echo A perintah dijalankan oleh dash tetapi dalam kasus bash , diumpankan sebagai input untuk read .

Apa yang terjadi adalah dash baca seluruh input (sebenarnya, satu blok teks) saat bash membaca satu baris pada satu waktu sebelum menjalankan perintah.

Untuk melakukannya, bash perlu membaca satu byte pada satu waktu untuk memastikan itu tidak membaca melewati baris baru, tetapi ketika inputnya adalah file biasa (seperti dalam kasus f saya file di atas, tetapi juga untuk dokumen di sini yang diimplementasikan bash sebagai file sementara, sementara dash menggunakan pipa), bash mengoptimalkannya dengan membaca per blok dan mencari kembali ke akhir baris, yang dapat Anda lihat dengan strace di 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
[...]

Ketika stdin adalah perangkat terminal, setiap read() mengembalikan baris seperti yang dikirim oleh terminal, jadi Anda biasanya melihat perilaku serupa di bash dan dash .

Dalam kasus Anda, Anda dapat melakukan:

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

atau lebih baik:

sudo sh -c '
  su test -c whoami
'

atau bahkan lebih baik:

sudo -u test whoami

Linux
  1. Apa shell favorit Anda untuk pekerjaan sysadmin?

  2. Mengapa Ekspresi Reguler Bekerja Di X Tapi Tidak Di Y?

  3. Mengapa ~/.bash_profile Tidak Berfungsi?

  1. Tujuan .bashrc Dan Bagaimana Cara Kerjanya?

  2. Mengapa Proses Pgid Anak Bukan Pid Orang Tua?

  3. Referensi Nama Edaran Dalam Fungsi Bash Shell, Tapi Tidak Di Ksh?

  1. Bagaimana Cara Membaca Seluruh Script Shell Sebelum Mengeksekusinya?

  2. Mengapa Regex Di Bash Hanya Bekerja Jika Itu Adalah Variabel Dan Tidak Secara Langsung??

  3. Mengapa SUID dinonaktifkan untuk skrip shell tetapi tidak untuk binari?