แบบพกพาเป็นอย่างไร / dev / stdin, / dev / stdout และ / dev / stderr?


55

บางครั้งผมต้องระบุเส้นทาง "เทียบเท่า" ของหนึ่งในลำธาร IO มาตรฐาน ( stdin, stdout, stderr) ตั้งแต่ 99% ของเวลาที่ฉันทำงานกับ Linux ฉันแค่เตรียมที่/dev/จะรับ/dev/stdinฯลฯ และสิ่งนี้ " ดูเหมือนจะทำสิ่งที่ถูกต้อง" แต่สิ่งหนึ่งที่ฉันไม่สบายใจเกี่ยวกับเหตุผลดังกล่าวอยู่เสมอ (เพราะแน่นอน "ดูเหมือนว่าจะทำงาน" จนกว่าจะไม่) นอกจากนี้ฉันไม่มีความรู้สึกที่ดีสำหรับวิธีการพกพาในการซ้อมรบนี้

ดังนั้นฉันมีคำถามสองสามข้อ:

  1. ในบริบทของลินุกซ์มันมีความปลอดภัย (ใช่ / ไม่ใช่) จะถือเอาstdin, stdoutและstderrด้วย/dev/stdin, /dev/stdoutและ /dev/stderr?

  2. โดยทั่วไปแล้วความเท่าเทียมนี้ " พกพาได้อย่างเพียงพอ" หรือไม่?

ฉันไม่พบการอ้างอิง POSIX ใด ๆ



คำตอบ:


36

มันสามารถใช้งานได้บน Linux กลับไปสู่ยุคก่อนประวัติศาสตร์ มันเป็นไม่ POSIX แม้ว่าเปลือกหอยที่เกิดขึ้นจริงหลายคน (รวมทั้ง AT & T kshและbash) จะจำลองมันถ้ามันไม่ได้อยู่ในระบบปฏิบัติการ; โปรดทราบว่าการจำลองนี้ใช้ได้เฉพาะในระดับเชลล์ (เช่นการเปลี่ยนเส้นทางหรือพารามิเตอร์บรรทัดคำสั่งไม่ใช่อาร์กิวเมนต์ที่ชัดเจนเช่นopen()) ที่กล่าวว่าควรมีอยู่ในระบบ Unix เชิงพาณิชย์ส่วนใหญ่ไม่ทางใดก็ทางหนึ่ง (บางครั้งมันจะสะกด/dev/fd/Nสำหรับจำนวนเต็มต่าง ๆNแต่ระบบส่วนใหญ่ที่มี symlink เป็น Linux และ * BSD ทำ)


13
แท้จริงแล้ว/dev/std{in,out,err}มีการระบุไว้เป็นพิเศษโดยไม่ได้เป็นส่วนหนึ่งของมาตรฐานPOSIX.1-2008
jw013

ดูเหมือนว่าashไม่รองรับ/dev/stdoutใน initrd ( git.razvi.ro/ ...... )
CMCDragonkai

@CMCDragonkai: นั่นไม่ใช่ / dev / stdout ที่เชลล์จัดการได้และคุณคาดหวังอะไรจาก initrd? มันเป็นสิ่งที่ขาดหายไปส่วนใหญ่เพื่อที่จะทำให้มันมีขนาดเล็กเท่ากับการใช้งานจริง
Joshua

22

/dev/std{in,out,err}ไฟล์เป็นปกติเพียง symlinks ไป/proc/self/fd/{0,1,2}(ตามลำดับ) เช่นนั้นไม่มีสิ่งใดที่ได้รับมากกว่าการใช้วิธีการที่กำหนด POSIX

หากคุณต้องการให้เป็นไปตาม POSIX วิธีที่ดีที่สุดในการทำเช่นนี้คือการใช้การเปลี่ยนเส้นทางเอาต์พุต เชลล์เปลี่ยนเส้นทางการส่งออกถูกกำหนดไว้ในมาตรฐาน POSIX นอกจากนี้หมายเลขตัวอธิบายไฟล์ STDIN, STDOUT, STDERR ก็เป็นส่วนหนึ่งของPOSIXเช่นกัน
ในระยะสั้นสิ่งต่าง ๆ เช่น>&2รับประกันการทำงาน

สิ่งสำคัญที่ควรทราบคือการใช้ STDIN, STDOUT และ STDERR นั้นขึ้นอยู่กับการเริ่มต้นของโปรแกรม หากโปรแกรมเริ่มต้นด้วย file descriptor 1 เป็นตัวจัดการเปิดสำหรับไฟล์แสดงว่าโปรแกรมของคุณต้องยอมรับมัน แม้ว่าคุณจะต้องเปิดโปรแกรมขึ้นมา/dev/stdoutสิ่งที่ต้องทำก็คือเปิดตัวอธิบายไฟล์ 1 ซึ่งยังคงชี้ไปที่ไฟล์นั้น
หากนี่คือสิ่งที่คุณพยายามหลีกเลี่ยงคุณต้องเปิด TTY โดยตรง โดยปกติแล้วไม่มีการเปลี่ยนทิศทางใด ๆ เกิดขึ้น STDIN, STDOUT และ STDERR ล้วน แต่เป็นตัวอธิบายไฟล์ที่เปิดอยู่ซึ่งชี้ไปที่ TTY เดียวกัน ไม่มีอะไรมากไปกว่านั้นอีกแล้ว


2
+1 โดยเฉพาะอย่างยิ่งส่วน "สิ่งสำคัญ"; ฉันจะแยกส่วนนี้ออกเป็นส่วน ๆ :)
Alois Mahdal

4
คุณช่วยอธิบายได้/proc/self/fd/1หรือไม่ว่า/dev/fd/1เป็นส่วนหนึ่งของ POSIX
Steven Penny

/dev/std???เป็น symlink ไปยัง/proc/self/fdบน Linux เท่านั้น
Stéphane Chazelas

5

POSIX 7 กล่าวว่าพวกเขาเป็นส่วนขยาย

คำจำกัดความฐานมาตรา 2.1.1 ข้อกำหนด:

ระบบอาจให้ส่วนขยายที่ไม่ได้มาตรฐาน คุณลักษณะเหล่านี้ไม่จำเป็นต้องใช้ใน POSIX.1-2008 และอาจรวมถึง แต่ไม่ จำกัด เพียง:

[ ... ]

  • ตัวอักษรไฟล์พิเศษเพิ่มเติมที่มีคุณสมบัติพิเศษ (ตัวอย่างเช่น  /dev/stdin,  /dev/stdoutและ  /dev/stderr)

พบโดย grepping POSIX HTML: รายการของฟังก์ชัน POSIX C API อยู่ที่ไหน

นอกจากนี้ยังวิจิตรพิสดารค่อนข้างuuencodeเครื่องมือที่จะช่วยให้/dev/stdoutผลมายากล :

การระบุตัวถูกดำเนินการdecode_pathname/dev/stdout จะต้องระบุว่า uudecode คือการใช้เอาต์พุตมาตรฐาน

เอกสารเคอร์เนล Linux บอกว่าทุกระบบควรมี

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

อย่างไรก็ตามฉันหาไม่พบว่ามีการสร้าง symlink เหล่านั้นในเคอร์เนลที่ใด


1

/ dev / {stdout, stdin, stderr} ทำงานใน Bash บนแพลตฟอร์มเหล่านี้:

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

แต่ล้มเหลวใน csh กับสิ่งเหล่านี้:

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
กรณีทดสอบของคุณคืออะไร? bashเป็นพิเศษที่จะสามารถรวบรวมเพื่อจัดการ/dev/fd/xด้วยตัวเองสำหรับการเปลี่ยนเส้นทางในระบบที่ไม่ได้มี/dev/fd
Stéphane Chazelas

@ StéphaneChazelasฉัน downvoted เพียงเพราะฉันสามารถเห็นสิ่งนี้ทำให้เข้าใจผิดโดยไม่ต้องชี้แจงว่า (ไม่มีการกระทำผิดไป Ole)
Evan Carroll

0

ปัญหาหนึ่งกับ/dev/stdoutเพื่อนคือคุณอาจไม่ได้รับอนุญาตให้เขียนถึงพวกเขาในบางสถานการณ์ ตัวอย่างเช่นฉันพบสิ่งนี้เมื่อเรียกใช้สคริปต์จากNixและฉันจินตนาการเครื่องมือที่คล้ายกันซึ่งเรียกใช้สคริปต์ในคุก / แซนด์บ็อกซ์ / คอนเทนเนอร์ / VMs / ฯลฯ อาจพบปัญหาที่คล้ายกัน

การใช้ไวยากรณ์เช่น1>&2ทำงานในกรณีเหล่านี้และเนื่องจากฉันรู้ว่าฉันกำลังทำงานใน Bash ฉันสามารถใช้การทดแทนกระบวนการสำหรับคำสั่งที่คาดว่าชื่อไฟล์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.