ฉันจะไปป์ stderr ได้อย่างไรและไม่ใช่ stdout?


981

ผมมีโปรแกรมที่เขียนข้อมูลไปยังstdoutและstderrและฉันต้องgrepผ่านอะไรมาเพื่อstderrขณะที่ไม่คำนึงถึงstdout

แน่นอนฉันสามารถทำได้ใน 2 ขั้นตอน:

command > /dev/null 2> temp.file
grep 'something' temp.file

แต่ฉันต้องการที่จะสามารถทำได้โดยไม่ต้องไฟล์ temp มีเทคนิคการวางท่อแบบอัจฉริยะหรือไม่?


คำถามที่คล้ายกัน แต่ยังคง stdout: unix.stackexchange.com/questions/3514/…
joeytwiddle

คำถามนี้มีไว้สำหรับ Bash แต่ก็คุ้มค่าที่จะกล่าวถึงบทความที่เกี่ยวข้องกับเชลล์ Bourne / Almquist
Stephen Niedzielski

10
ฉันคาดหวังอะไรแบบนี้: command 2| othercommand. Bash นั้นสมบูรณ์แบบมากจนการพัฒนาสิ้นสุดลงในปี 1982 ดังนั้นเราจะไม่เห็นว่าเป็นการทุบตีฉันกลัว
Rolf

คำตอบ:


1189

ก่อนเปลี่ยนเส้นทาง stderr ไปยัง stdout - the pipe; จากนั้นเปลี่ยนเส้นทาง stdout ไปที่/dev/null(โดยไม่เปลี่ยนตำแหน่งที่ stderr กำลังทำงาน):

command 2>&1 >/dev/null | grep 'something'

สำหรับรายละเอียดของการเปลี่ยนเส้นทาง I / O ในความหลากหลายทั้งหมดดูบทการเปลี่ยนเส้นทางในคู่มืออ้างอิง Bash

โปรดทราบว่าลำดับของการเปลี่ยนเส้นทาง I / O ถูกตีความจากซ้ายไปขวา แต่มีการตั้งค่าไพพ์ก่อนการเปลี่ยนเส้นทาง I / O จะถูกตีความ ตัวอธิบายไฟล์เช่น 1 และ 2 เป็นการอ้างอิงถึงคำอธิบายไฟล์แบบเปิด การดำเนินการ2>&1ทำให้ file descriptor 2 aka stderr อ้างถึงคำอธิบายไฟล์เปิดเดียวกันกับ file descriptor 1 aka stdout กำลังอ้างถึง (ดูdup2()และopen()) >/dev/nullจากนั้นการดำเนินการจะเปลี่ยน file descriptor 1 เพื่อให้มันอ้างถึง open description description /dev/nullแต่ไม่ได้เปลี่ยนความจริงที่ file descriptor 2 อ้างถึง open file description ซึ่ง file descriptor 1 ชี้ไปที่ - คือไพพ์


44
ฉันเพิ่งสะดุดข้าม / dev / stdout / dev / stderr / dev / stdin เมื่อวันก่อนและฉันสงสัยว่ามันเป็นวิธีที่ดีในการทำสิ่งเดียวกันหรือไม่? ฉันคิดเสมอว่า 2> & 1 ค่อนข้างงงงวย ดังนั้นสิ่งที่ชอบ: command 2> /dev/stdout 1> /dev/null | grep 'something'
Mike Lyons

17
คุณสามารถใช้/dev/stdoutet al, /dev/fd/Nหรือการใช้งาน พวกมันจะมีประสิทธิภาพน้อยกว่าเล็กน้อยยกเว้นกรณีที่เปลือกถือว่าเป็นกรณีพิเศษ สัญกรณ์ตัวเลขที่บริสุทธิ์ไม่เกี่ยวข้องกับการเข้าถึงไฟล์ตามชื่อ แต่การใช้อุปกรณ์หมายถึงการค้นหาชื่อไฟล์ คุณสามารถวัดว่าเป็นที่ถกเถียงกันหรือไม่ ฉันชอบความรัดกุมของสัญกรณ์ตัวเลข - แต่ฉันใช้มันมานาน (มากกว่าหนึ่งในสี่ศตวรรษ; อุ๊ย!) ที่ฉันไม่มีคุณสมบัติที่จะตัดสินข้อดีของมันในโลกสมัยใหม่
Jonathan Leffler

23
@ Jonathan Leffler: ฉันใช้ปัญหาเล็กน้อยกับคำอธิบายข้อความธรรมดาของคุณ'เปลี่ยนเส้นทาง stderr ไปยัง stdout แล้ว stdout เป็น / dev / null' - เนื่องจากเราต้องอ่านเชนการเปลี่ยนเส้นทางจากขวาไปซ้าย (ไม่ใช่จากซ้ายไปขวา) เรา นอกจากนี้ยังควรปรับคำอธิบายข้อความธรรมดาของเรานี้: 'เปลี่ยนเส้นทาง stdout / dev / null แล้ว stderr ไปยังที่ที่ stdout เคยเป็น'
Kurt Pfeifle

116
@ KurtPfeifle: au ตรงกันข้าม! เราต้องอ่านโซ่การเปลี่ยนเส้นทางจากซ้ายไปขวาเนื่องจากเป็นวิธีที่เชลล์ประมวลผล การดำเนินการครั้งแรกคือ2>&1, ซึ่งหมายถึง 'เชื่อมต่อ stderr กับ file descriptor ที่ stdout กำลังจะไป' การดำเนินการที่สองคือ 'เปลี่ยน stdout เพื่อไปที่/dev/null' โดยปล่อย stderr ไปที่ stdout ดั้งเดิมคือท่อ เชลล์แยกสิ่งต่าง ๆ ที่สัญลักษณ์ไปป์ก่อนดังนั้นการเปลี่ยนเส้นทางไปป์เกิดขึ้นก่อน2>&1หรือ>/dev/nullเปลี่ยนเส้นทาง แต่นั่นคือทั้งหมด การดำเนินการอื่น ๆ จากซ้ายไปขวา (จากขวาไปซ้ายจะไม่ทำงาน)
Jonathan Leffler

14
สิ่งที่ทำให้ฉันประหลาดใจมากเกี่ยวกับเรื่องนี้ก็คือมันใช้งานได้บน Windows เช่นกัน (หลังจากเปลี่ยนชื่อ/dev/nullเป็น Windows ที่เทียบเท่าnul)
Michael Burr

364

หรือเพื่อสลับเอาต์พุตจากข้อผิดพลาดมาตรฐานและเอาต์พุตมาตรฐานให้ใช้:

command 3>&1 1>&2 2>&3

สิ่งนี้จะสร้าง file descriptor ใหม่ (3) และกำหนดให้กับตำแหน่งเดียวกับ 1 (เอาต์พุตมาตรฐาน) จากนั้นกำหนด fd 1 (เอาต์พุตมาตรฐาน) ไปยังตำแหน่งเดียวกับ fd 2 (ข้อผิดพลาดมาตรฐาน) และกำหนด fd 2 ในที่สุด ) ไปยังตำแหน่งเดียวกับ fd 3 (เอาต์พุตมาตรฐาน)

ข้อผิดพลาดมาตรฐานพร้อมใช้งานเป็นเอาต์พุตมาตรฐานและเอาต์พุตมาตรฐานเก่าถูกเก็บรักษาไว้ในข้อผิดพลาดมาตรฐาน สิ่งนี้อาจเกินความจริง แต่หวังว่าจะให้รายละเอียดเพิ่มเติมเกี่ยวกับตัวอธิบายไฟล์ Bash (มีเก้าขั้นตอนสำหรับแต่ละกระบวนการ)


100
การปรับแต่งขั้นสุดท้ายจะเป็นการ3>&-ปิดตัวอธิบายที่คุณสร้างขึ้นจาก stdout
Jonathan Leffler

1
เราสามารถสร้าง file descriptor ที่มีstderrและอื่น ๆ ที่มีการรวมกันของstderrและstdout? ในคำอื่น ๆ สามารถstderrไปสองไฟล์ที่แตกต่างกันในครั้งเดียว?
Stuart

ต่อไปนี้ยังพิมพ์ข้อผิดพลาดไปยัง stdout ฉันพลาดอะไรไป ls -l not_a_file 3> & 1 1> & 2 2> & 3> ข้อผิดพลาด.txt
user48956

1
@ JonasDahlbæk: การบิดเป็นปัญหาของความยุ่งเหยิงเป็นหลัก ในสถานการณ์ที่คลาดเคลื่อนอย่างแท้จริงมันอาจสร้างความแตกต่างระหว่างกระบวนการตรวจจับและไม่ตรวจจับ EOF แต่ต้องใช้สถานการณ์ที่แปลกประหลาดมาก
Jonathan Leffler

1
ข้อควรระวัง : สิ่งนี้ถือว่า FD 3 ยังไม่ได้ใช้ไม่ปิดและไม่ทำการสลับการอธิบายไฟล์ 1 และ 2 ดังนั้นคุณจึงไม่สามารถใช้คำสั่งนี้กับคำสั่งอื่นได้ ดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติมและวิธีแก้ไข สำหรับไวยากรณ์ที่สะอาดกว่าสำหรับ {ba, z} sh ให้ดูคำตอบนี้
Tom Hale

218

ใน Bash คุณสามารถเปลี่ยนเส้นทางไปยัง subshell โดยใช้การทดแทนกระบวนการ :

command > >(stdlog pipe)  2> >(stderr pipe)

สำหรับกรณีที่อยู่ในมือ:

command 2> >(grep 'something') >/dev/null

1
ทำงานได้ดีมากสำหรับการส่งออกไปยังหน้าจอ คุณมีความคิดใด ๆ หรือไม่ที่เนื้อหาที่ ungrepped ปรากฏขึ้นอีกครั้งหากฉันเปลี่ยนเส้นทางการส่งออก grep เป็นไฟล์ หลังจากcommand 2> >(grep 'something' > grep.log)grep.log มีเอาต์พุตเดียวกันกับ ungrepped.log ตั้งแต่command 2> ungrepped.log
ทิม

9
2> >(stderr pipe >&2)ใช้ มิฉะนั้นเอาต์พุตของ "stderr pipe" จะผ่าน "stdlog pipe"
ceving

ใช่! 2> >(...)งานฉันพยายาม2>&1 > >(...)แต่มันไม่ได้
datdinhquoc

นี่คือตัวอย่างเล็ก ๆ ที่อาจช่วยฉันในครั้งต่อไปที่ฉันค้นหาวิธีการทำเช่นนี้ พิจารณาต่อไป ... awk -f /new_lines.awk <in-content.txt > out-content.txt 2> >(tee new_lines.log 1>&2 ) ในกรณีนี้ผมอยากจะยังมองเห็นสิ่งที่ออกมาเป็นข้อผิดพลาดบนคอนโซลของฉัน แต่ STDOUT กำลังไปที่ไฟล์เอาต์พุต ดังนั้นภายใน sub-shell คุณจำเป็นต้องเปลี่ยน STDOUT นั้นกลับไปที่ STDERR ภายในวงเล็บ ในขณะที่ใช้งานได้เอาต์พุต STDOUT จากteeคำสั่งจะเริ่มต้นที่ท้ายout-content.txtไฟล์ ดูเหมือนจะไม่สอดคล้องกับฉัน
จะ

@datdinhquoc ฉันทำมันอย่างใดเช่น2>&1 1> >(dest pipe)
Alireza Mohamadi

195

รวมคำตอบที่ดีที่สุดเข้าด้วยกันหากคุณ:

command 2> >(grep -v something 1>&2)

... จากนั้น stdout ทั้งหมดจะถูกเก็บรักษาไว้เป็น stdout และ stderr ทั้งหมดจะถูกเก็บรักษาไว้เป็น stderr แต่คุณจะไม่เห็นบรรทัดใด ๆ ใน stderr ที่มีสตริง "บางอย่าง"

สิ่งนี้มีข้อได้เปรียบที่ไม่เหมือนใครในการไม่ย้อนกลับหรือยกเลิก stdout และ stderr หรือการรวมเข้าด้วยกันและไม่ใช้ไฟล์ชั่วคราวใด ๆ


ไม่ได้command 2> >(grep -v something)(ไม่1>&2) เหมือนกันหรือไม่
Francesc Rosas

11
ไม่ถ้าไม่มี stderr ที่กรองแล้วจะถูกส่งไปที่ stdout
Pinko

1
นี่คือสิ่งที่ฉันต้องการ - tar เปลี่ยน "ไฟล์ที่เปลี่ยนแปลงเมื่อเราอ่าน" สำหรับไดเรกทอรีเสมอดังนั้นเพียงแค่ต้องการกรองว่าหนึ่งบรรทัด แต่ดูว่ามีข้อผิดพลาดอื่น ๆ เกิดขึ้นหรือไม่ ดังนั้นtar cfz my.tar.gz mydirectory/ 2> >(grep -v 'changed as we read it' 1>&2)ควรทำงาน
razzed

มันผิดที่จะพูดว่า "เริ่มต้นด้วยสตริง" ไม่มีอะไรเกี่ยวกับไวยากรณ์ที่แสดงของ grep ที่จะทำให้มันแยกเฉพาะบรรทัดที่ขึ้นต้นด้วยสตริงที่กำหนด เส้นจะถูกแยกออกหากพวกเขามีสตริงที่กำหนดที่ใดก็ได้ในพวกเขา
Mike Nakis

@ MikeNakis ขอบคุณ - แก้ไขแล้ว! (นั่นคือที่เหลือจากร่างคำตอบเดิมของฉันซึ่งมันทำให้รู้สึก ... )
Pinko

102

มันง่ายมากที่จะเห็นภาพสิ่งต่าง ๆ ถ้าคุณคิดว่าเกิดอะไรขึ้นกับ "การเปลี่ยนเส้นทาง" และ "ท่อ" การเปลี่ยนเส้นทางและไปป์ในทุบตีทำสิ่งหนึ่ง: แก้ไขที่ตัวอธิบายไฟล์กระบวนการ 0, 1 และ 2 ชี้ไปที่ (ดู / proc / [pid] / fd / *)

เมื่อเป็นท่อหรือ "|" โอเปอเรเตอร์ปรากฏอยู่บนบรรทัดคำสั่งสิ่งแรกที่เกิดขึ้นคือทุบตีสร้าง Fifo และชี้ให้คำสั่ง FD 1 ของฝ่ายซ้ายด้านซ้ายมาที่ Fifo นี้และชี้ให้คำสั่ง FD 0 ของฝ่ายขวาเหมือนกัน

ถัดไปตัวดำเนินการเปลี่ยนเส้นทางสำหรับแต่ละด้านจะถูกประเมินจากซ้ายไปขวาและการตั้งค่าปัจจุบันจะถูกใช้เมื่อใดก็ตามที่การทำซ้ำของ descriptor เกิดขึ้น สิ่งนี้มีความสำคัญเนื่องจากตั้งแต่ตั้งค่าท่อไปก่อน FD1 (ด้านซ้าย) และ FD0 (ด้านขวา) จะเปลี่ยนไปจากสิ่งที่พวกเขาอาจเคยเป็นมาก่อนและการทำซ้ำของสิ่งเหล่านี้จะสะท้อนถึงความจริงนั้น

ดังนั้นเมื่อคุณพิมพ์สิ่งต่อไปนี้:

command 2>&1 >/dev/null | grep 'something'

นี่คือสิ่งที่เกิดขึ้นตามลำดับ:

  1. สร้าง pipe (fifo) "คำสั่ง FD1" ถูกชี้ไปที่ไพพ์นี้ "grep FD0" ยังชี้ไปที่ท่อนี้
  2. "command FD2" ถูกชี้ไปที่ตำแหน่งปัจจุบันของ "command FD1" (ไปป์)
  3. "คำสั่ง FD1" ถูกชี้ไปที่ / dev / null

ดังนั้นเอาต์พุตทั้งหมดที่ "คำสั่ง" เขียนไปยัง FD 2 (stderr) ทำให้ไปยังไพพ์และอ่านโดย "grep" ที่อีกด้านหนึ่ง เอาต์พุตทั้งหมดที่ "คำสั่ง" เขียนไปยัง FD 1 (stdout) ทำให้มันเป็น / dev / null

หากคุณรันสิ่งต่อไปนี้แทน:

command >/dev/null 2>&1 | grep 'something'

นี่คือสิ่งที่เกิดขึ้น:

  1. ไพพ์ถูกสร้างขึ้นและ "คำสั่ง FD 1" และ "grep FD 0" จะชี้ไปที่
  2. "คำสั่ง FD 1" ถูกชี้ไปที่ / dev / null
  3. "command FD 2" จะชี้ไปที่จุดใด FD 1 ปัจจุบัน (/ dev / null)

ดังนั้น stdout และ stderr ทั้งหมดจาก "command" ไปที่ / dev / null ไม่มีอะไรไปที่ไพพ์ดังนั้น "grep" จะปิดลงโดยไม่แสดงอะไรบนหน้าจอ

นอกจากนี้โปรดทราบว่าการเปลี่ยนเส้นทาง (ตัวอธิบายไฟล์) สามารถเป็นแบบอ่านอย่างเดียว (<), เขียนอย่างเดียว (>) หรืออ่านเขียน (<>)

บันทึกสุดท้าย การเขียนโปรแกรมไปยัง FD1 หรือ FD2 นั้นขึ้นอยู่กับโปรแกรมเมอร์หรือไม่ แนวปฏิบัติที่ดีในการเขียนโปรแกรมกำหนดว่าข้อความแสดงข้อผิดพลาดควรไปที่ FD 2 และเอาท์พุทปกติไปที่ FD 1 แต่คุณมักจะพบว่าการเขียนโปรแกรมเลอะเทอะที่ผสมทั้งสองหรือละเว้นการประชุม


6
คำตอบที่ดีจริงๆ ข้อเสนอแนะข้อหนึ่งของฉันคือการแทนที่ "Fifo" ที่คุณใช้เป็นครั้งแรกด้วย "Fifo (ชื่อไพพ์)" ฉันใช้ลีนุกซ์มาระยะหนึ่งแล้ว แต่ก็ไม่เคยที่จะเรียนรู้ว่าเป็นคำศัพท์อีกคำสำหรับไพพ์ที่มีชื่อ สิ่งนี้จะช่วยฉันจากการมองมัน แต่อีกครั้งฉันจะไม่ได้เรียนรู้สิ่งอื่น ๆ ที่ฉันเห็นเมื่อฉันพบสิ่งนั้น!
Mark Edington

3
@MarkEdington โปรดทราบว่า FIFO เป็นเพียงอีกวาระหนึ่งสำหรับไปป์ที่มีชื่อในบริบทของท่อและ IPC ในบริบททั่วไปเพิ่มเติม FIFO หมายถึงเข้าก่อนออกก่อนซึ่งอธิบายถึงการแทรกและการลบออกจากโครงสร้างข้อมูลคิว
Loomchild

5
@ Loomchild แน่นอน ประเด็นของความคิดเห็นของฉันคือแม้ในฐานะนักพัฒนาที่มีประสบการณ์ฉันไม่เคยเห็น FIFO ใช้เป็นคำพ้องสำหรับไพพ์ที่มีชื่อ กล่าวอีกอย่างคือฉันไม่รู้สิ่งนี้: en.wikipedia.org/wiki/FIFO_(computing_and_electronics)#Pipes - การชี้แจงว่าคำตอบจะช่วยให้ฉันประหยัดเวลาได้
Mark Edington

39

หากคุณกำลังใช้ Bash ให้ใช้:

command >/dev/null |& grep "something"

http://www.gnu.org/software/bash/manual/bashref.html#Pipelines


4
Nope |&เท่ากับ2>&1ที่รวม stdout และ stderr คำถามที่ถามอย่างชัดเจนสำหรับการส่งออกโดยไม่ต้อง stdout
Profpatsch

3
„ หากใช้ '| &' ข้อผิดพลาดมาตรฐานของ command1 เชื่อมต่อกับอินพุตมาตรฐานของ command2 ผ่านไพพ์ มันเป็นชวเลขสำหรับ 2> & 1 |” ใช้คำต่อคำจากย่อหน้าที่สี่ที่ลิงก์ของคุณ
Profpatsch

9
@Profpatsch: คำตอบของเคนถูกต้องแล้วดูว่าเขาเปลี่ยนเส้นทาง stdout ไปเป็นโมฆะก่อนที่จะรวม stdout และ stderr ดังนั้นคุณจะได้รับเฉพาะ stderr เท่านั้นเนื่องจาก stdout ถูกลดลงไปที่ / dev / null
Luciano

3
แต่ฉันยังพบว่าคำตอบของคุณผิด>/dev/null |&ขยายไปถึง>/dev/null 2>&1 | และหมายความว่า stdout inode ว่างเปล่าไปที่ pipe เพราะไม่มีใคร (# 1 # 2 ทั้งสองถูกผูกติดกับ / dev / null inode) ถูกผูกเข้ากับ stdout inode (เช่นls -R /tmp/* >/dev/null 2>&1 | grep iจะว่างเปล่า แต่ls -R /tmp/* 2>&1 >/dev/null | grep iจะทำให้ # 2 ซึ่งเชื่อมโยงกับ stdout inode จะไปป์)
ผลไม้

3
Ken Sharp ฉันทดสอบแล้วและ( echo out; echo err >&2 ) >/dev/null |& grep "."ไม่แสดงผลใด ๆ (ที่เราต้องการ "ผิดพลาด") man bashพูดว่าถ้า | & ถูกใช้…นั้นเป็นการจดชวเลข 2> & 1 | การเปลี่ยนทิศทางโดยนัยของข้อผิดพลาดมาตรฐานไปยังเอาต์พุตมาตรฐานถูกดำเนินการหลังจากการเปลี่ยนทิศทางใด ๆ ที่ระบุโดยคำสั่ง ดังนั้นก่อนอื่นเราเปลี่ยนทิศทางของคำสั่ง FD1 เป็นโมฆะจากนั้นเราเปลี่ยนคำสั่ง FD2 ของคำสั่งไปยังจุดที่ FD1 ชี้ไปเช่น null ดังนั้น FD0 ของ grep จึงไม่มีอินพุต ดูstackoverflow.com/a/18342079/69663สำหรับคำอธิบายในเชิงลึกเพิ่มเติม
unhammer

11

สำหรับผู้ที่ต้องการเปลี่ยนเส้นทาง stdout และ stderr อย่างถาวรไปยังไฟล์ grep บน stderr แต่ให้ stdout เขียนข้อความไปยัง tty:

# save tty-stdout to fd 3
exec 3>&1
# switch stdout and stderr, grep (-v) stderr for nasty messages and append to files
exec 2> >(grep -v "nasty_msg" >> std.err) >> std.out
# goes to the std.out
echo "my first message" >&1
# goes to the std.err
echo "a error message" >&2
# goes nowhere
echo "this nasty_msg won't appear anywhere" >&2
# goes to the tty
echo "a message on the terminal" >&3

6

สิ่งนี้จะเปลี่ยนทิศทาง command1 stderr ไปเป็น command2 stdin ในขณะที่ออก command1 stdout ตามเดิม

exec 3>&1
command1 2>&1 >&3 3>&- | command2 3>&-
exec 3>&-

นำมาจากLDP


2

ฉันเพิ่งได้คำตอบสำหรับการส่งstdoutคำสั่งหนึ่งไปยังอีกคำสั่งstderrหนึ่งโดยใช้ไพพ์ที่มีชื่อ

นี่ไง

mkfifo stdout-target
mkfifo stderr-target
cat < stdout-target | command-for-stdout &
cat < stderr-target | command-for-stderr &
main-command 1>stdout-target 2>stderr-target

อาจเป็นความคิดที่ดีที่จะลบท่อที่ระบุชื่อหลังจากนั้น


0

คุณสามารถใช้เปลือก RC

ก่อนติดตั้งแพ็คเกจ (น้อยกว่า 1 MB)

นี่เป็นตัวอย่างของวิธีที่คุณจะละทิ้งเอาต์พุตมาตรฐานและข้อผิดพลาดมาตรฐานไพพ์ถึงgrepในrc:

find /proc/ >[1] /dev/null |[2] grep task

คุณสามารถทำได้โดยไม่ทิ้ง Bash:

rc -c 'find /proc/ >[1] /dev/null |[2] grep task'

ดังที่คุณอาจสังเกตเห็นคุณสามารถระบุไฟล์ descriptor ที่คุณต้องการ pip โดยใช้เครื่องหมายวงเล็บหลังไพพ์

ตัวอธิบายไฟล์มาตรฐานจะถูกนับเช่น:

  • 0: อินพุตมาตรฐาน
  • 1: เอาต์พุตมาตรฐาน
  • 2: ข้อผิดพลาดมาตรฐาน

-3

ฉันลองติดตามแล้วพบว่าทำงานได้ดี

command > /dev/null 2>&1 | grep 'something'

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