ระงับข้อความ stderr ในสคริปต์ทุบตี


48

พิจารณาชื่อสคริปต์ต่อไปนี้ (โง่เล็กน้อย) 'test1.sh':

#/bin/bash
#
sleep 10 &
echo sleep pid = $!
pkill sleep

เมื่อฉันเรียกใช้ฉันไม่เพียง แต่เอาท์พุทของเสียงก้องเท่านั้น แต่ยังรายงานการตายของการนอนหลับบน stderr ด้วย:

$ ./test1.sh
sleep pid = 3551
./test1.sh: line 5:  3551 Terminated              sleep 10

ในกรณีนี้ฉันต้องการระงับการพิมพ์ไปยัง stderr ฉันรู้ว่าฉันสามารถทำได้ในบรรทัดคำสั่งเช่นเดียวกับใน:

$ ./test1.sh 2> /dev/null

... แต่มีวิธีที่จะระงับมันจากภายในสคริปต์หรือไม่ (ฉันรู้ว่าฉันสามารถตัดมันในสคริปต์ที่สองและให้ wrapper เปลี่ยนเส้นทาง แต่ต้องมีบางสิ่งที่ง่ายกว่า ... )


คุณลองเพิ่มการเปลี่ยนเส้นทาง 2> / dev / null หลังจาก pkill sleep หรือไม่?
ราหุล

@ ราอูล: ใช่ฉันทำ - pkill ไม่ได้สร้างข้อความทุบตีคือ
fearless_fool

ฉันใช้ kill แทน pkill และไม่ได้ stderr แปลก ..
ราหุล

@ ราอูล: มันอาจจะเป็นสิ่งที่สร้างขึ้นเมื่อเทียบกับสิ่งที่ไม่ได้สร้างขึ้นใช่ไหม คุณลองกับ pkill ด้วยหรือเปล่า
fearless_fool

ใช่ฉันเชื่อว่ามันเป็น ฉันได้รับข้อผิดพลาดเดียวกันกับ pkill แต่ไม่ใช่กับ kill ในขณะที่ใช้ kill ฉันใช้ pid แทนชื่อ proc
ราหุล

คำตอบ:


72

คุณถูก; pkill ไม่ได้สร้างข้อความ bash คือ คุณแนะนำว่า

$ ./test1.sh 2> /dev/null

เป็นทางออกที่เป็นไปได้ เมื่อ UVV ชี้ให้เห็นการกระทำที่เท่าเทียมกันจากภายในสคริปต์คือ

exec 2> /dev/null

สิ่งนี้จะเปลี่ยนเส้นทาง stderr สำหรับสคริปต์ไป/dev/null จากคำสั่งนี้จนกว่ามันจะเปลี่ยนกลับ วิธีการเปลี่ยนกลับงุ่มง่ามรวมถึง

exec 2> /dev/tty

ซึ่งเปลี่ยนเส้นทาง stderr ไปยังสถานี นี่อาจเป็น (แต่ไม่จำเป็น) ที่เดิม

หรือ

exec 2>&1

ซึ่งกำหนดให้ stderr เหมือนกับ stdout และมีแนวโน้มที่จะผิด

วิธีที่เชื่อถือได้มากขึ้นคือ

exec 3> & 2
exec 2> / dev / null
(ทำสิ่งที่คุณไม่ต้องการเห็น stderr) 
exec 2> & 3

ซึ่งบันทึก stderr ดั้งเดิมใน file descriptor 3 และเรียกคืนภายหลัง

วิธีอื่นในการระงับการประกาศการตายของกระบวนการรวมถึง

(sleep 10 & pkill sleep) 2> /dev/null

และ

{ sleep 10 & pkill sleep;} 2> /dev/null

ซึ่งเปลี่ยน stderr สำหรับคำสั่งที่จัดกลุ่มเท่านั้น


นี่เป็นคำตอบที่ยอดเยี่ยมและละเอียดมาก ขอบคุณครับ!
คีแนนซ์ลอเรนซ์

มีอันตรายใด ๆ ที่เกี่ยวข้องกับการบันทึกstdinและstderrไปยัง file descriptors ใหม่ส่ง descriptor ดั้งเดิมไปที่/dev/nullแล้วกู้คืนหรือไม่
Alexej Magura

ฉันคิดว่าถ้าคุณใช้โปรแกรมที่เขียนถึง file descriptor 3 (หรือ 4) การดำเนินการนั้นจะล้มเหลวภายใต้สถานการณ์ปกติ แต่สามารถเขียนโปรแกรมเพื่อเพิกเฉยต่อความล้มเหลวและดำเนินการต่อโดยไม่ต้องรายงาน ถ้าอย่างนั้นคุณก็ไม่รู้ แต่ถ้าตัวอธิบายไฟล์ของคุณ 1 (หรือ 2) เป็น“ parked” บนไฟล์ descriptor 3 (หรือ 4) จากนั้นโปรแกรมนั้นก็จะเขียนลง stdout หรือ stderr ของสคริปต์ของคุณทันที แต่นั่นเป็นตัวอย่างที่วางแผนไว้มากและยังคงเป็นอันตรายน้อยที่สุด คุณมีบางอย่างในใจ?
สกอตต์

1
FWIW ฉันชอบวิธีการจัดกลุ่มของ Scott เช่น{ sleep 10 & pkill sleep;} 2> /dev/null
fearless_fool

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