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 suyang memicu masalah.
/dev/stdoutadalah 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 usernamemasuk. Ketika Anda sudo su username2, kepemilikan /dev/pts/1tidak berubah, dan username2tidak 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 helloberfungsi tetapi echo hello > /dev/stdoutgagal.
Salah satu solusinya adalah dengan membuat username2anggota kelompok tty, tetapi itu akan memberikan username2izin untuk menulis kepada anggota mana pun , yang mungkin tidak diinginkan.
Solusi lain adalah login ke username2akun daripada menggunakan su, sehingga /dev/stdoutmenunjuk ke pseudoterminal yang baru dialokasikan milik username2. Ini mungkin tidak praktis.
Solusi lain adalah dengan memodifikasi skrip Anda sehingga mereka tidak merujuk /dev/stdoutdan /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/stdoutdan /dev/stderrdiperlakukan 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/stdoutet al diperlakukan secara khusus apakah file ada atau tidak. Fitur ini diperkenalkan di bash 2.04, dan NEWSfile 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_STDINdidefinisikan (ini ditentukan ketika bash dibangun dari sumber).
Sejauh yang saya tahu, tidak ada versi bash yang dirilis telah membuat penanganan khusus /dev/stdouttanpa syarat - kecuali beberapa distribusi telah menambalnya.
Jadi solusi lain (yang belum saya coba) adalah untuk mengambil sumber bash , memodifikasi redir.cuntuk 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/stdoutdan /dev/stderrdengan 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/stdoutdan /dev/stderrbekerja dengan benar. Masalah ini hanya muncul ketika Anda suke akun lain atau melakukan sesuatu yang serupa; jika Anda cukup masuk ke akun, izinnya sudah benar.
ls -l /dev/stdout /dev/stderrdanls -lL /dev/stdout /dev/stderr?