bash: / dev / stderr: Izin ditolak

19

Setelah memutakhirkan ke versi rilis baru, bashskrip saya mulai meludah kesalahan:

bash: /dev/stderr: Permission denied

dalam versi sebelumnya Bash akan mengenali secara internal nama-nama file tersebut (itulah sebabnya pertanyaan ini bukan duplikat dari yang ini ) dan melakukan hal yang benar (tm) , namun, ini telah berhenti berfungsi sekarang. Apa yang dapat saya lakukan untuk dapat menjalankan skrip saya lagi dengan sukses?

Saya telah mencoba menambahkan pengguna yang menjalankan skrip ke grup tty, tetapi ini tidak ada bedanya (bahkan setelah logout dan kembali).

Saya dapat mereproduksi ini di baris perintah tanpa masalah:

$ echo test > /dev/stdout
bash: /dev/stdout: Permission denied
$ echo test > /dev/stderr
bash: /dev/stderr: Permission denied
$ ls -l /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stdout -> /proc/self/fd/1
$ ls -lL /dev/stdout /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stdout
$ echo $BASH_VERSION
4.2.24(1)-release

Pada sistem yang lebih lama (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release
0xC0000022L
sumber
1
Apa output dari ls -l /dev/stdout /dev/stderrdan ls -lL /dev/stdout /dev/stderr?
Keith Thompson
@Keith: lihat pertanyaan saya yang diedit. Apakah itu berarti bahwa Bash telah sepenuhnya meninggalkan penanganan internal ini? Pada sistem yang lebih lama, symlink ini tidak ada dan kode berfungsi tanpa masalah. Catatan, ini berjalan tiruan melalui sudo su username2 -...
0xC0000022L
Apa versi bash yang Anda gunakan? echo $BASH_VERSION
jippie
1
Apa versi lama dan baru (sebelum dan sesudah OS dan bash Anda?
Keith Thompson

Jawaban:

41

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.

Keith Thompson
sumber
Kepemilikan TTY harus berubah. Itulah yang digunakan ConsoleKit (alias pam_ck_connector.sountuk).
Mikel
Sebenarnya, saya bisa saja salah. Harus menggali lebih banyak.
Mikel
Di sistem saya, /proc/self/fd/1perizinannya diperbarui, tapi itu tidak ada gunanya, karena itu adalah symlink. Terjadi pada Fedora juga, yang tampaknya mengesampingkan ConsoleKit.
Mikel
1

Sebenarnya alasan untuk ini adalah bahwa udev secara khusus menetapkan izin untuk 0620 pada perangkat tty dan su tidak mengubah kepemilikan atau izin juga tidak seharusnya. Dalam pandangan saya ini membuat kita dalam situasi yang membuat / dev / std * non-portable.

Solusi sederhananya adalah dengan meletakkan "mesg y" di / etc / profile (atau profil tingkat atas apa pun yang ingin Anda gunakan) karena ini mengubah izin perangkat tty Anda ke 0622. Saya tidak begitu menyukainya tetapi mungkin lebih baik daripada mengubah aturan udev.

Wheely
sumber
"msg y" tidak berfungsi
Luciano
Tunggu ... mungkin mencari Bash menangani beberapa nama file khusus ketika mereka digunakan dalam pengalihan di halaman manual Bash.
0xC0000022L
0

Sebagai pengguna Linux yang lama saya baru-baru ini membuat sistem Ubuntu 64 bit 12,04 LTS baru dan bingung mengapa skrip bash saya tidak berfungsi - izin ditolak - dan saya kemudian menemukan utas ini. Saya pikir masalahnya mungkin karena sesuatu di OS baru.

Pada akhirnya ternyata saya bodoh menggunakan alat UI untuk mengatur izin pada /homedirektori saya , dan masalahnya terkait drive . Yang pasti, saya membuat tempdirektori /optdan menemukan skrip saya akan berjalan dengan baik dari sana. Setelah saya memperbaiki /homeizin drive semuanya kembali normal.

Satu misteri kecil terpecahkan. mendesah

Ichiro Furusato
sumber
2
Ini pasti kesalahan yang berbeda. Memodifikasi sesuatu di / home tidak memengaruhi / dev.
ott--
-1

Ini adalah pertanyaan lama, tapi saya pikir masih sangat relevan, maka inilah solusi yang saya temukan yang tidak disebutkan di sini.

Saya menemukan pertanyaan ini karena saya juga telah melihat masalah dalam perintah eksekusi 'su' yang diaktifkan akun seperti ini di bash:

echo test > /dev/stderr

Karena semua yang saya coba lakukan adalah mengarahkan ulang stdout ke stderr, yang berikut ini mencapai hal yang sama, dan itu berfungsi bahkan dalam akun aktif su:

echo test 1>&2
Marcin K
sumber