Saya tidak berpikir ini sepenuhnya masalah bash.
Dalam komentar, Anda mengatakan bahwa Anda melihat kesalahan ini setelah melakukannya
sudo su username2
saat masuk sebagai username
. Itu su
yang memicu masalah.
/dev/stdout
adalah symlink ke /proc/self/fd/1
, yang merupakan symlink ke, misalnya /dev/pts/1
,. /dev/pts/1
, Yang merupakan pseudoterminal sebuah, dimiliki oleh, dan ditulis oleh, username
; kepemilikan itu diberikan saat username
masuk. Ketika Anda sudo su username2
, kepemilikan /dev/pts/1
tidak berubah, dan username2
tidak memiliki izin menulis.
Saya berpendapat bahwa ini adalah bug. /dev/stdout
seharusnya , pada dasarnya, alias untuk aliran output standar, tetapi di sini kita melihat situasi di mana echo hello
berfungsi tetapi echo hello > /dev/stdout
gagal.
Salah satu solusinya adalah dengan membuat username2
anggota kelompok tty
, tetapi itu akan memberikan username2
izin untuk menulis kepada anggota mana pun , yang mungkin tidak diinginkan.
Solusi lain adalah login ke username2
akun daripada menggunakan su
, sehingga /dev/stdout
menunjuk ke pseudoterminal yang baru dialokasikan milik username2
. Ini mungkin tidak praktis.
Solusi lain adalah dengan memodifikasi skrip Anda sehingga mereka tidak merujuk /dev/stdout
dan /dev/stderr
; misalnya, ganti ini:
echo OUT > /dev/stdout
echo ERR > /dev/stderr
dengan ini:
echo OUT
echo ERR 1>&2
Saya melihat ini di sistem saya sendiri, Ubuntu 12.04, dengan bash 4.2.24 - meskipun dokumen bash ( info bash
) pada sistem saya mengatakan itu /dev/stdout
dan /dev/stderr
diperlakukan secara khusus ketika digunakan dalam pengalihan. Tetapi bahkan jika bash tidak memperlakukan nama-nama itu secara khusus, mereka harus tetap bertindak sebagai setara untuk stream I / O standar. (POSIX tidak menyebutkan /dev/std{in,out,err}
, jadi mungkin sulit untuk berpendapat bahwa ini adalah bug.)
Melihat versi bash lama, dokumentasi menyiratkan bahwa /dev/stdout
et al diperlakukan secara khusus apakah file ada atau tidak. Fitur ini diperkenalkan di bash 2.04, dan NEWS
file untuk versi itu mengatakan:
Kode pengalihan sekarang menangani beberapa nama file khusus: / dev / fd / N, / dev / stdin, / dev / stdout, dan / dev / stderr, terlepas dari apakah mereka ada dalam sistem file atau tidak.
Tetapi jika Anda memeriksa kode sumber ( redir.c
), Anda akan melihat bahwa penanganan khusus diaktifkan hanya jika simbol HAVE_DEV_STDIN
didefinisikan (ini ditentukan ketika bash dibangun dari sumber).
Sejauh yang saya tahu, tidak ada versi bash yang dirilis telah membuat penanganan khusus /dev/stdout
tanpa syarat - kecuali beberapa distribusi telah menambalnya.
Jadi solusi lain (yang belum saya coba) adalah untuk mengambil sumber bash , memodifikasi redir.c
untuk membuat /dev/*
penanganan khusus tanpa syarat, dan menggunakan versi dibangun kembali Anda daripada yang datang dengan sistem Anda. Ini mungkin berlebihan, meskipun.
RINGKASAN:
OS Anda, seperti milik saya, tidak menangani kepemilikan dan izin dari /dev/stdout
dan /dev/stderr
dengan benar. bash seharusnya memperlakukan nama-nama ini secara khusus dalam pengalihan, tetapi pada kenyataannya ia melakukannya hanya jika file tidak ada. Itu tidak masalah jika /dev/stdout
dan /dev/stderr
bekerja dengan benar. Masalah ini hanya muncul ketika Anda su
ke akun lain atau melakukan sesuatu yang serupa; jika Anda cukup masuk ke akun, izinnya sudah benar.
ls -l /dev/stdout /dev/stderr
danls -lL /dev/stdout /dev/stderr
?