Seberapa portabel / dev / stdin, / dev / stdout dan / dev / stderr?


55

Kadang-kadang saya perlu menentukan "jalan-setara" dari salah satu IO standar stream ( stdin, stdout, stderr). Karena 99% dari waktu saya bekerja dengan Linux, saya hanya perlu /dev/untuk mendapatkan /dev/stdin, dll, dan ini " sepertinya melakukan hal yang benar". Tetapi, untuk satu hal, saya selalu merasa tidak nyaman dengan alasan yang demikian (karena, tentu saja, "tampaknya berhasil" sampai tidak berhasil). Selain itu, saya tidak memiliki akal yang baik untuk seberapa portabel manuver ini.

Jadi saya punya beberapa pertanyaan:

  1. Dalam konteks Linux, apakah aman (ya / tidak) untuk menyamakan stdin, stdoutdan stderrdengan /dev/stdin, /dev/stdout, dan /dev/stderr?

  2. Secara umum, apakah kesetaraan ini "cukup portabel "?

Saya tidak dapat menemukan referensi POSIX.



Jawaban:


36

Sudah tersedia di Linux kembali ke masa prasejarahnya. Ini bukan POSIX, meskipun banyak shell aktual (termasuk AT&T kshdan bash) akan mensimulasikannya jika tidak ada di OS; perhatikan bahwa simulasi ini hanya berfungsi pada level shell (yaitu redirection atau parameter baris perintah, bukan sebagai argumen eksplisit untuk eg open()). Yang mengatakan, itu harus tersedia pada sebagian besar sistem Unix komersial, satu atau lain cara (kadang-kadang dieja /dev/fd/Nuntuk berbagai bilangan bulat N, tetapi sebagian besar sistem dengan itu akan memberikan symlink seperti Linux dan * BSD lakukan).


13
Memang, /dev/std{in,out,err}secara khusus terdaftar sebagai bukan bagian dari standar POSIX.1-2008 .
jw013

Tampaknya itu ashtidak mendukung /dev/stdoutinitrd ( git.razvi.ro/… )
CMCDragonkai

@ CMCDragonkai: Itu bukan / dev / stdout yang bisa ditangani oleh shell, dan apa yang Anda harapkan dari initrd? Ini kehilangan sebagian besar kebaikan untuk membuatnya sekecil praktis.
Joshua

22

yang /dev/std{in,out,err}file biasanya hanya symlink ke /proc/self/fd/{0,1,2}(masing-masing). Karena itu tidak ada yang diperoleh dari menggunakan metode yang didefinisikan POSIX.

Jika Anda ingin mematuhi POSIX, cara terbaik untuk melakukannya adalah dengan menggunakan pengalihan output. Redirection output shell didefinisikan dalam standar POSIX . Selain itu nomor deskriptor file STDIN, STDOUT, STDERR juga merupakan bagian dari POSIX .
Singkatnya, hal-hal seperti >&2dijamin bekerja.

Satu hal penting yang perlu diperhatikan adalah penggunaan STDIN, STDOUT, dan STDERR bersifat subyektif terhadap bagaimana program dimulai. Jika program dimulai dengan deskriptor file 1 sebagai pegangan terbuka untuk file, maka program Anda hanya harus menerimanya. Bahkan jika Anda memiliki program terbuka /dev/stdout, semua itu akan lakukan adalah membuka file deskriptor 1 yang masih akan mengarah ke file itu.
Jika ini yang ingin Anda lakukan, Anda perlu membuka TTY secara langsung. Biasanya, tanpa ada pengalihan, STDIN, STDOUT, dan STDERR semuanya hanya buka deskriptor file yang menunjuk ke TTY yang sama. Sama sekali tidak ada yang lebih dari itu.


2
+1, terutama untuk bagian "satu hal penting"; Saya akan mencerna bagian ini :)
Alois Mahdal

4
Bisakah Anda mengklarifikasi jika /proc/self/fd/1atau /dev/fd/1merupakan bagian dari POSIX?
Steven Penny

/dev/std???hanya symlinks /proc/self/fddi Linux.
Stéphane Chazelas

5

POSIX 7 mengatakan itu adalah ekstensi.

Definisi Dasar , Bagian 2.1.1 Persyaratan:

Sistem dapat memberikan ekstensi non-standar. Ini adalah fitur yang tidak diperlukan oleh POSIX.1-2008 dan mungkin termasuk, tetapi tidak terbatas pada:

[...]

  • File karakter khusus tambahan dengan sifat khusus (misalnya,  /dev/stdin,  /dev/stdout, dan  /dev/stderr)

Ditemukan dengan memahami POSIX HTML: Di mana daftar fungsi POSIX C API?

Juga cukup aneh, uuencodealat ini memberikan /dev/stdoutefek ajaib :

Menentukan operand decode_pathname/dev/stdout harus menunjukkan bahwa uudecode akan menggunakan output standar.

Dokumentasi kernel Linux mengatakan semua sistem harus memilikinya.

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

Namun, saya tidak dapat menemukan di mana symlink tersebut dibuat di kernel (distro disediakan?).


1

/ dev / {stdout, stdin, stderr} berfungsi di Bash pada platform ini:

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

Tetapi gagal dalam csh pada ini:

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
Apa uji kasus Anda? bashistimewa karena dapat dikompilasi untuk ditangani /dev/fd/xsendiri untuk pengalihan pada sistem yang tidak memiliki/dev/fd
Stéphane Chazelas

@ StéphaneChazelas Saya telah menurunkan suara hanya karena saya dapat melihat ini menyesatkan tanpa klarifikasi itu (jangan tersinggung Ole).
Evan Carroll

0

Satu masalah dengan /dev/stdoutdan teman adalah bahwa Anda mungkin tidak memiliki izin untuk menulis kepada mereka dalam keadaan tertentu. Sebagai contoh, saya pernah menjumpai ini ketika memohon skrip dari Nix , dan saya membayangkan alat serupa yang menjalankan skrip di penjara / kotak pasir / wadah / VMs / dll. mungkin mengalami masalah serupa.

Menggunakan sintaks seperti 1>&2bekerja dalam kasus ini dan, karena saya tahu saya akan berjalan di Bash, saya bisa menggunakan proses substitusi untuk perintah yang mengharapkan nama file.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.