Làm thế nào di động là / dev / stdin, / dev / stdout và / dev / stderr?


55

Thỉnh thoảng tôi cần phải xác định một "con đường tương đương" của một trong những con suối IO tiêu chuẩn ( stdin, stdout, stderr). Vì 99% thời gian tôi làm việc với Linux, tôi chỉ cần /dev/chuẩn bị để nhận /dev/stdin, v.v., và điều này " dường như làm đúng". Nhưng, đối với một điều, tôi luôn cảm thấy khó chịu về một lý do như vậy (bởi vì, tất nhiên, "nó dường như hoạt động" cho đến khi nó không hoạt động). Hơn nữa, tôi không có ý thức tốt cho việc cơ động này là như thế nào.

Vì vậy, tôi có một vài câu hỏi:

  1. Trong bối cảnh của Linux, là nó an toàn (có / không) để đánh đồng stdin, stdoutstderrvới /dev/stdin, /dev/stdout/dev/stderr?

  2. Tổng quát hơn, sự tương đương này là " di động đầy đủ "?

Tôi không thể tìm thấy bất kỳ tài liệu tham khảo POSIX.



Câu trả lời:


36

Nó đã có sẵn trên Linux từ thời tiền sử. Nó không phải là POSIX, mặc dù nhiều shell thực tế (bao gồm cả AT & T kshbash) sẽ mô phỏng nó nếu nó không có trong HĐH; lưu ý rằng mô phỏng này chỉ hoạt động ở cấp độ vỏ (tức là chuyển hướng hoặc tham số dòng lệnh, không phải là đối số rõ ràng với ví dụ open()). Điều đó nói rằng, nó nên có sẵn trên hầu hết các hệ thống Unix thương mại, bằng cách này hay cách khác (đôi khi nó được đánh vần /dev/fd/Ncho các số nguyên khác nhau N, nhưng hầu hết các hệ thống sẽ cung cấp liên kết tượng trưng như Linux và * BSD làm).


13
Thật vậy, /dev/std{in,out,err}được liệt kê cụ thể không phải là một phần của tiêu chuẩn POSIX.1-2008 .
jw013

Có vẻ như ashkhông hỗ trợ /dev/stdouttrong initrd ( git.razvi.ro/ Kẻ )
CMCDragonkai

@CMCDragonkai: Đó không phải là / dev / stdout có thể được xử lý bởi shell, và bạn mong đợi gì về initrd? Nó thiếu hầu hết các tính chất để làm cho nó nhỏ như thực tế.
Joshua

22

các /dev/std{in,out,err}tập tin thường chỉ là symlink đến /proc/self/fd/{0,1,2}(tương ứng). Vì vậy, không có gì đạt được khi sử dụng các phương thức được xác định POSIX.

Nếu bạn muốn tuân thủ POSIX, cách tốt nhất để làm điều này là sử dụng chuyển hướng đầu ra. Chuyển hướng đầu ra Shell được xác định trong tiêu chuẩn POSIX . Ngoài ra, các số mô tả tệp STDIN, STDOUT, STDERR cũng là một phần của POSIX .
Trong ngắn hạn, những thứ như >&2được đảm bảo để làm việc.

Một điều quan trọng cần lưu ý là việc sử dụng STDIN, STDOUT và STDERR là chủ quan đối với cách chương trình được bắt đầu. Nếu chương trình được bắt đầu với mô tả tệp 1 là một điều khiển mở đối với một tệp, thì chương trình của bạn chỉ phải chấp nhận nó. Ngay cả khi bạn đã mở chương trình /dev/stdout, tất cả những gì nó sẽ làm là mở mô tả tệp 1 vẫn sẽ trỏ đến tệp đó.
Nếu đây là những gì bạn đang cố gắng để có được xung quanh, bạn cần phải mở TTY trực tiếp. Thông thường, không có bất kỳ sự chuyển hướng nào đang diễn ra, STDIN, STDOUT và STDERR đều chỉ là các mô tả tệp đang mở trỏ đến cùng một TTY. Hoàn toàn không có gì hơn thế.


2
+1, đặc biệt đối với phần "một điều quan trọng"; Tôi sẽ tiêu hóa phần này theo từng phần :)
Alois Mahdal

4
Bạn có thể làm rõ nếu /proc/self/fd/1hoặc /dev/fd/1là một phần của POSIX?
Steven Penny

/dev/std???chỉ là các liên kết tượng trưng /proc/self/fdtrên Linux.
Stéphane Chazelas

5

POSIX 7 cho biết chúng là phần mở rộng.

Định nghĩa cơ sở , Mục 2.1.1 Yêu cầu:

Hệ thống có thể cung cấp các phần mở rộng không chuẩn. Đây là những tính năng không được POSIX.1-2008 yêu cầu và có thể bao gồm, nhưng không giới hạn ở:

[...]

  • Bổ sung tập tin ký tự đặc biệt với tính chất đặc biệt (ví dụ  /dev/stdin,  /dev/stdoutvà  /dev/stderr)

Được tìm thấy bằng cách lấy mã POSIX HTML: Danh sách các hàm POSIX C nằm ở đâu?

Cũng khá kỳ lạ, uuencodecông cụ này mang lại /dev/stdouthiệu ứng kỳ diệu :

Chỉ định toán hạng decode_pathname/dev/stdout sẽ chỉ ra rằng uudecode sẽ sử dụng đầu ra tiêu chuẩn.

Tài liệu nhân Linux nói rằng tất cả các hệ thống nên có nó.

https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/devices.rst

Compulsory links
These links should exist on all systems:
/dev/fd       /proc/self/fd   symbolic   File descriptors
/dev/stdin    fd/0            symbolic   stdin file descriptor
/dev/stdout   fd/1            symbolic   stdout file descriptor
/dev/stderr   fd/2            symbolic   stderr file descriptor

Tuy nhiên, tôi không thể tìm thấy những liên kết tượng trưng đó được tạo trong kernel (distro cung cấp?).


1

/ dev / {stdout, stdin, stderr} hoạt động trong Bash trên các nền tảng này:

Linux debian-ppc 3.16.0-4-powerpc #1 Debian 3.16.7-ckt25-1 (2016-03-06) ppc GNU/Linux
HP-UX hpux-ia6 B.11.31 U ia64 0107668277 unlimited-user license
AIX aix7 1 7 000ACFDE4C00
FreeBSD freebsd.polarhome.com 10.0-RELEASE-p7 FreeBSD 10.0-RELEASE-p7 #0: Tue Jul  8 06:37:44 UTC 2014     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  amd64
HP-UX hpux64 B.11.11 U 9000/785 2000587908 unlimited-user license
Darwin macosx 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:26:45 PDT 2012; root:xnu-1699.32.7~1/RELEASE_I386 i386
GNU hurd 0.7 GNU-Mach 1.6-486/Hurd-0.7 i686-AT386 GNU
Linux mandriva.polarhome.com 2.6.33.7-desktop-2mnb #1 SMP Mon Sep 20 18:19:20 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux
SunOS openindiana 5.11 oi_148 i86pc i386 i86pc
MirBSD miros.polarhome.com 10 Kv#10uAF-20110818 GENERIC#1330 i386
Linux pidora 3.12.23-2.20140626git25673c3.rpfr20.armv6hl.bcm2708 #1 PREEMPT Fri Jul 4 16:06:10 EDT 2014 armv6l armv6l armv6l GNU/Linux
QNX qnx 6.5.0 2010/07/09-14:44:03EDT x86pc x86
NetBSD netbsd.polarhome.com 6.1.3 NetBSD 6.1.3 (GENERIC) i386
OpenBSD openbsd.polarhome.com 4.9 GENERIC#671 i386
Linux raspbian 3.18.7+ #755 PREEMPT Thu Feb 12 17:14:31 GMT 2015 armv6l GNU/Linux
SCO_SV scosysv 5 6.0.0 i386
Linux redhat.polarhome.com 3.17.4-301.fc21.x86_64 #1 SMP Thu Nov 27 19:09:10 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
SunOS solaris-x86 5.11 11.3 i86pc i386 i86pc
Linux suse 3.4.63-2.44-desktop #1 SMP PREEMPT Wed Oct 2 11:18:32 UTC 2013 (d91a619) x86_64 x86_64 x86_64 GNU/Linux
SunOS solaris 5.10 Generic_147147-26 sun4u sparc SUNW,Sun-Fire-V210
Linux ubuntu 3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17 20:50:15 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
UnixWare unixware 5 7.1.4 i386 x86at SCO UNIX_SVR5
OSF1 tru64.polarhome.com V5.1 2650 alpha
Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u2 (2016-01-02) x86_64 GNU/Linux

Nhưng thất bại trong csh về những điều này:

HP-UX hpux-ia6 B.11.31 U ia64 0107668277 unlimited-user license
Linux centos.polarhome.com 2.6.18-409.el5 #1 SMP Tue Mar 15 18:13:50 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
HP-UX hpux64 B.11.11 U 9000/785 2000587908 unlimited-user license
AIX aix7 1 7 000ACFDE4C00
SCO_SV scosysv 5 6.0.0 i386
SunOS solaris-x86 5.11 11.3 i86pc i386 i86pc
SunOS openindiana 5.11 oi_148 i86pc i386 i86pc
SunOS solaris 5.10 Generic_147147-26 sun4u sparc SUNW,Sun-Fire-V210
UnixWare unixware 5 7.1.4 i386 x86at SCO UNIX_SVR5
OSF1 tru64.polarhome.com V5.1 2650 alpha

6
Trường hợp thử nghiệm của bạn là gì? bashlà đặc biệt vì nó có thể được biên dịch để tự xử lý /dev/fd/xcác chuyển hướng trên các hệ thống không có/dev/fd
Stéphane Chazelas

@ StéphaneChazelas Tôi đã đánh giá thấp chỉ vì tôi có thể thấy điều này gây hiểu lầm mà không cần làm rõ (không xúc phạm đến Ole).
Evan Carroll

0

Một vấn đề với /dev/stdoutvà bạn bè là bạn có thể không được phép viết thư cho họ trong những trường hợp nhất định. Ví dụ: tôi đã gặp phải điều này khi gọi các tập lệnh từ Nix và tôi tưởng tượng các công cụ tương tự chạy các tập lệnh trong tù / hộp cát / thùng chứa / VM / v.v. có thể gặp phải vấn đề tương tự.

Sử dụng cú pháp như 1>&2đã làm việc trong các trường hợp này và, vì tôi biết tôi đang chạy trong Bash, tôi có thể sử dụng thay thế quy trình cho các lệnh mong đợi tên tệp.

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.