วิธีการ unbuffer stdout เมื่อไพพ์คำสั่งใน cmd.exe ภายใต้ Windows


3

รับดังต่อไปนี้:

C:\>perl -E " say STDOUT 111; say STDERR 222; say STDOUT 333; "
111
222
333

C:\>perl -E " say STDOUT 111; say STDERR 222; say STDOUT 333; " | cat
222
111
333

ลำดับของเอาต์พุตไม่ถูกสงวนไว้เมื่อคำสั่ง piping เนื่องจาก stdout ถูกบัฟเฟอร์และ stderr ถูกยกเลิกการบัฟเฟอร์ stdout สามารถเชื่อถือได้อย่างไรเพื่อให้คำสั่งนั้นถูกเก็บไว้เมื่อไพพ์คำสั่ง?

ฉันค้นหาทั่วพยายามหาวิธีแก้ปัญหาฉันลองใช้สคริปต์เช่นunbufferจากexpectแพคเกจใน cygwin และ Linux แต่ใช้งานได้เฉพาะภายใน Cygwin (ด้านนอกของมันในที่ดินเปล่า cmd.exe คำสั่งยังไม่ถูกต้อง stderr ยังมาเร็วกว่าที่คาด) เหมือนกันstdbuf -i0 -o0 -e0 ...

ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชมอย่างมาก.


ปัญหาไม่ได้เป็นบัฟเฟอร์จริงๆ แต่การเปลี่ยนเส้นทาง: stdoutข้อความล่าช้าโดยถูกส่งไปยังcatในขณะที่ข้อความจะstderrถูกเขียนโดยตรงไปยังเทอร์มินัลเมื่อสร้างขึ้น ทางออกที่ง่ายที่สุดที่จะเปลี่ยนเส้นทางstderrไปยังท่อก่อนที่จะเป็นในstdout ... 2>&1 | catมีวิธีการเพื่อให้มั่นใจว่าการทำงานไม่เป็นจะขัดขวางการดำเนินการของcat perl
AFH

@AFH ขอบคุณ แต่ฉันได้ลองแล้ว แต่ก็ยังไม่เรียบร้อย: C:\>perl -E " say STDOUT 111; say STDERR 222; say STDOUT 333; " 2>&1 | cat=>222 111 333
szr

ฉันจะไม่คาดหวังว่า: หากไม่มีperlWindows ก็ไม่ง่ายที่จะทดสอบ ฉันเดาว่าเป็นเพราะทั้งสองสตรีมเอาต์พุตถูกบัฟเฟอร์และเอาต์พุตถูกสร้างขึ้นเฉพาะเมื่อปิดทั้งคู่ซึ่งในกรณีนี้การสั่งซื้อจะขึ้นอยู่กับลำดับของการปิดไฟล์ ในโปรแกรม C คุณสามารถตั้งค่าสตรีมเอาท์พุทให้เป็นแบบไม่มีบัฟเฟอร์หรือโปรแกรมต่อfflushจากfputsนั้น แต่ฉันไม่ทราบว่าเป็นไปได้หรือไม่perl- อาจจะเรียกใช้ฟังก์ชัน C เพื่อทำมัน
AFH

คำตอบ:


1

บัฟเฟอร์ I / O เลเยอร์เริ่มต้นของ Perl และไม่ได้ใช้stdioโดยค่าเริ่มต้นซึ่งเป็นสาเหตุunbufferและstdbuf(ซึ่งแก้ไขstdioบัฟเฟอร์เริ่มต้น) ไม่ทำงาน

Perl ให้วิธีการของตนเองในการควบคุมชั้น I / O ที่ใช้แม้ว่า: PERLIOตัวแปรสภาพแวดล้อม ต่อเอกสารก็ควรจะเป็นไปได้ที่จะเรียกใช้ก่อนที่จะใช้คำสั่งหรือ Windows พื้นเมืองดิบจัดการตาม I / O ซึ่งอาจจะยังคงทดลอง / รถ, อย่างใดอย่างหนึ่งควรหลีกเลี่ยงพฤติกรรมบัฟเฟอร์ปกติโดยตรงไปที่การเรียกระบบดิบman perlrunset PERLIO=:unixset PERLIO=:win32

สมมติว่าcatตัวเองไม่ได้บัฟเฟอร์ (ฉันเชื่อว่าใช้การอ่านและเขียนแบบดิบโดยไม่บัฟเฟอร์ดังนั้นควรเป็นอย่างนี้) แต่ก็ยังไม่รับประกันพฤติกรรมที่คุณต้องการ Perl สามารถส่งข้อมูลไปยังcatทันที แต่ถ้าไม่catสามารถอ่านและเขียนกลับคืนได้เร็วกว่า Perl ก็สามารถย้ายไปที่บรรทัดถัดไปแล้วพิมพ์ไปยังSTDERRคุณจะยังเห็นSTDERRผลลัพธ์ก่อน ในการทดสอบในท้องถิ่น (บน Linux แต่มันควรจะสวยเหมือนกัน) กับPERLIO=:unixท่อเพื่อcatผมเห็นผลดังต่อไปนี้:

222111

333

แล้ว:

222
111
333

แล้ว:

111222

333

จากนั้น (สองครั้งติดต่อกัน):

111
222
333

ประเด็นก็คือถึงแม้จะมีการบัฟเฟอร์ออกจากสมการท่อก็จะแนะนำสภาพการแข่งขันเนื่องจากการขนานระดับกระบวนการ วิธีเดียวที่จะทำให้แน่ใจว่าสตรีมทั้งสองไปที่cat:

perl -E "say STDOUT 111; say STDERR 222; say STDOUT 333;" 2>&1 | cat

ผลลัพธ์ที่สม่ำเสมอ:

111
222
333

เพราะข้อมูลทั้งหมดจะถูกส่งไปยังcatทันทีก่อนที่จะprintดำเนินการต่อไป วิธีเดียวที่จะได้รับการสั่งซื้อที่เชื่อถือได้ (ส่วนใหญ่) คือการนอนหลับระหว่างภาพพิมพ์ (อนุญาตให้catชนะการแข่งขันด้วยperl)

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