bash: / dev / stderr: Quyền bị từ chối


19

Sau khi nâng cấp lên phiên bản phát hành mới, bashtập lệnh của tôi bắt đầu phát sinh lỗi:

bash: /dev/stderr: Permission denied

trong các phiên bản trước, Bash sẽ nhận ra bên trong các tên tệp đó (đó là lý do tại sao câu hỏi này không phải là bản sao của câu hỏi này ) và thực hiện đúng (tm) , tuy nhiên, hiện tại nó đã ngừng hoạt động. Tôi có thể làm gì để có thể chạy lại tập lệnh của mình thành công?

Tôi đã thử thêm người dùng chạy tập lệnh vào nhóm tty, nhưng điều này không tạo ra sự khác biệt (ngay cả sau khi đăng xuất và đăng nhập lại).

Tôi có thể tái tạo điều này trên dòng lệnh mà không gặp vấn đề gì:

$ 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

Trên hệ thống cũ hơn (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release

1
Đầu ra của ls -l /dev/stdout /dev/stderrvà là ls -lL /dev/stdout /dev/stderrgì?
Keith Thompson

@Keith: xem câu hỏi chỉnh sửa của tôi. Điều đó có nghĩa là Bash đã hoàn toàn từ bỏ việc xử lý nội bộ này? Trên các hệ thống cũ, các liên kết tượng trưng này không tồn tại và mã vẫn hoạt động mà không gặp vấn đề gì. Lưu ý, điều này đang được mạo danh thông qua sudo su username2 -...
0xC0000022L

Bạn đang sử dụng phiên bản bash nào? echo $BASH_VERSION
jippie

1
Các phiên bản cũ và mới (trước và sau hệ điều hành của bạn và bash là gì?
Keith Thompson

Câu trả lời:


41

Tôi không nghĩ rằng đây hoàn toàn là một vấn đề bash.

Trong một bình luận, bạn nói rằng bạn đã thấy lỗi này sau khi thực hiện

sudo su username2

khi đăng nhập như username. Đó là suđiều gây ra vấn đề.

/dev/stdoutlà một liên kết tượng trưng /proc/self/fd/1, ví dụ như một liên kết tượng trưng /dev/pts/1. /dev/pts/1, đó là một giả hành, được sở hữu bởi, và có thể ghi bởi username; quyền sở hữu đó đã được cấp khi usernameđăng nhập. Khi bạn sudo su username2, quyền sở hữu /dev/pts/1không thay đổi và username2không có quyền viết.

Tôi cho rằng đây là một lỗi. /dev/stdout nên được, trên thực tế, một bí danh cho dòng đầu ra tiêu chuẩn, nhưng ở đây chúng ta thấy một tình huống mà echo hellocác công trình nhưng echo hello > /dev/stdoutthất bại.

Một cách giải quyết khác là tạo username2thành viên của nhóm tty, nhưng điều đó sẽ cho username2phép viết cho bất kỳ tty nào , điều này có thể là không mong muốn.

Một cách giải quyết khác là đăng nhập vào username2tài khoản thay vì sử dụng su, để /dev/stdoutchỉ ra một giả hành mới được phân bổ thuộc sở hữu của username2. Điều này có thể không thực tế.

Một cách giải quyết khác là sửa đổi tập lệnh của bạn để chúng không tham chiếu /dev/stdout/dev/stderr; ví dụ: thay thế cái này:

echo OUT > /dev/stdout
echo ERR > /dev/stderr

bằng cách này

echo OUT
echo ERR 1>&2

Tôi thấy điều này trên hệ thống của riêng tôi, Ubuntu 12.04, với bash 4.2.24 - mặc dù tài liệu bash ( info bash) trên hệ thống của tôi nói điều đó /dev/stdout/dev/stderrđược xử lý đặc biệt khi được sử dụng trong các chuyển hướng. Nhưng ngay cả khi bash không xử lý các tên đó một cách đặc biệt, chúng vẫn nên đóng vai trò tương đương cho các luồng I / O tiêu chuẩn. (POSIX không đề cập đến /dev/std{in,out,err}, vì vậy có thể khó tranh luận rằng đây là một lỗi.)

Nhìn vào các phiên bản cũ của bash, tài liệu ngụ ý rằng /dev/stdoutet al được xử lý đặc biệt cho dù các tệp có tồn tại hay không. Tính năng này được giới thiệu trong bash 2.04 và NEWStệp cho phiên bản đó cho biết:

Mã chuyển hướng hiện xử lý một số tên tệp đặc biệt: / dev / fd / N, / dev / stdin, / dev / stdout và / dev / stderr, cho dù chúng có trong hệ thống tệp hay không.

Nhưng nếu bạn kiểm tra mã nguồn ( redir.c), bạn sẽ thấy rằng xử lý đặc biệt chỉ được bật nếu biểu tượng HAVE_DEV_STDINđược xác định (điều này được xác định khi bash được xây dựng từ nguồn).

Theo như tôi có thể nói, không có phiên bản bash nào được phát hành đã khiến việc xử lý đặc biệt của /dev/stdoutet al trở nên vô điều kiện - trừ khi một số bản phân phối đã vá nó.

Vì vậy, một cách giải quyết khác (mà tôi chưa thử) sẽ là lấy các nguồn bash , sửa đổi redir.cđể /dev/*xử lý đặc biệt vô điều kiện và sử dụng phiên bản được xây dựng lại của bạn thay vì phiên bản đi kèm với hệ thống của bạn. Điều này có lẽ là quá mức cần thiết, mặc dù.

TÓM LƯỢC :

Hệ điều hành của bạn, giống như của tôi, không xử lý quyền sở hữu và quyền /dev/stdout/dev/stderrchính xác. bash được cho là xử lý các tên này đặc biệt trong các chuyển hướng, nhưng thực tế nó chỉ làm như vậy nếu các tệp không tồn tại. Điều đó sẽ không quan trọng nếu /dev/stdout/dev/stderrlàm việc chính xác. Vấn đề này chỉ hiển thị khi bạn suđến một tài khoản khác hoặc làm điều gì đó tương tự; nếu bạn chỉ cần đăng nhập vào một tài khoản, các quyền là chính xác.


Quyền sở hữu của TTY nên thay đổi. Đó là những gì ConsoleKit (còn gọi pam_ck_connector.solà dành cho).
Mikel

Thật ra, tôi có thể sai. Sẽ phải đào thêm.
Mikel

Trên các hệ thống của tôi, /proc/self/fd/1có các quyền của nó được cập nhật, nhưng điều đó là vô nghĩa, vì đó là một liên kết tượng trưng. Xảy ra trên Fedora, dường như loại trừ ConsoleKit.
Mikel

1

Trên thực tế, lý do cho điều này là udev đặc biệt đặt các quyền thành 0620 trên các thiết bị tty và su không thay đổi quyền sở hữu hoặc quyền cũng không nên. Theo quan điểm của tôi, điều này khiến chúng ta rơi vào tình huống khiến / dev / std * không thể di động.

Giải pháp đơn giản là đặt "mesg y" trong / etc / profile (hoặc bất kỳ cấu hình cấp cao nhất nào bạn muốn sử dụng) vì điều này thay đổi quyền của thiết bị tty của bạn thành 0622. Tôi không thực sự thích điều đó nhưng có lẽ tốt hơn thay đổi các quy tắc udev.


"Thông điệp y" không hoạt động
Luciano

Đợi ... có thể tìm kiếm Bash xử lý một số tên tệp đặc biệt khi chúng được sử dụng trong các chuyển hướng trong trang man của Bash.
0xC0000022L

0

Là một người dùng Linux lâu năm, gần đây tôi đã thiết lập một hệ thống Ubuntu 64 bit 12.04 LTS mới và đã bị bối rối về lý do tại sao các tập lệnh bash của tôi không hoạt động - quyền bị từ chối - và sau đó tôi đã tìm thấy chủ đề này. Tôi nghĩ vấn đề có thể là do một cái gì đó trong hệ điều hành mới.

Cuối cùng, hóa ra tôi đã ngu ngốc sử dụng một công cụ UI để đặt quyền trên /homethư mục của mình và vấn đề liên quan đến ổ đĩa . Để chắc chắn, tôi đã tạo một tempthư mục trên /optvà thấy các tập lệnh của tôi sẽ chạy tốt từ đó. Khi tôi sửa lỗi /homeổ đĩa, mọi thứ trở lại bình thường.

Một bí ẩn nhỏ đã được giải quyết. thở dài


2
Đây phải là một lỗi khác nhau. Sửa đổi một cái gì đó trong / nhà không ảnh hưởng / dev.
ott--

-1

Đây là một câu hỏi cũ, nhưng tôi nghĩ vẫn còn rất phù hợp, do đó đây là giải pháp tôi thấy không được đề cập ở đây.

Tôi đã gặp câu hỏi này vì tôi cũng đã thấy các vấn đề trong lệnh thực thi tài khoản được chuyển đổi 'su' như thế này trong bash:

echo test > /dev/stderr

Vì tất cả những gì tôi đang cố gắng làm là chuyển hướng thiết bị xuất chuẩn sang thiết bị xuất chuẩn, nên những điều sau đây đạt được như vậy và nó hoạt động ngay cả trong tài khoản được chuyển đổi 'su':

echo test 1>&2
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.