Linux ลดพฤติกรรมและ stderr


11

ฉันกำลังดูผลลัพธ์ของคำสั่งที่ซับซ้อนด้วยlessปัญหาคือสิ่งที่stderrหายไป stderrสายตามปกติได้รับการจดทะเบียน inbetween สายภายในstdout lessฉันต้องการให้พวกเขาพิมพ์ไปยังคอนโซลและเมื่อฉันออกlessไปดูพวกเขาที่นั่นด้วยกัน

ผมทราบดีว่าอาจจะมีวิธีแก้ปัญหานี้ไม่ฉันอ่านเกี่ยวกับteeและmultiteeแต่โชคไม่เพื่อให้ห่างไกล


2
คุณกำลังบอกวิธีเปลี่ยน stderr ไปยัง stdout แต่นั่นไม่ใช่สิ่งที่ฉันต้องการ ฉันไม่ต้องการให้ stderr ผสมกับ stdout ภายในน้อยลง ฉันต้องการ stderr ที่จะอยู่ในสถานีเมื่อฉันออกน้อย

หากstderrมีการเปลี่ยนเส้นทางการstdoutส่งออกทั้งหมดเพื่อstderr จะstdoutนำมาผสมกับการแสดงผลปกติ การส่งออกไปยังท่อlessจะแสดงทั้ง
โปรแกรมเมอร์บางคนเพื่อน

หากฉันไม่สนใจ "stderr ที่จะอยู่ใน terminal เมื่อฉันออกน้อย" ฉันแนะนำให้กด Ctrl-L lessเพื่อทาสีหน้าจอ
kamae

คำตอบ:


10

อาจจะ

command 2> command.err | less; cat command.err; rm command.err

ภาคผนวก

ต่อไปนี้เป็นคำชี้แจงสำหรับชาวบ้านที่ละเลยที่จะอ่านคำถามอย่างรอบคอบและผู้ที่ไม่ได้อ่านความคิดเห็นที่ชัดเจนของ OP ข้างต้น

haelix ชี้:

บรรทัด stderr ตามปกติจะได้รับการจดทะเบียนในระหว่างบรรทัด stdout ภายในน้อย

และในความคิดเห็นสำหรับผู้ตอบเร็วเขียนว่า:

คุณกำลังบอกวิธีเปลี่ยน stderr ไปยัง stdout แต่นั่นไม่ใช่สิ่งที่ฉันต้องการ ฉันไม่ต้องการให้ stderr ผสมกับ stdout ภายในน้อยลง ฉันต้องการ stderr ที่จะอยู่ในสถานีเมื่อฉันออกน้อย

ปัญหาน่าจะเป็นแพลตฟอร์มเฉพาะมันเป็นสิ่งที่ฉันได้พบบนแพลตฟอร์ม Unix SVR4 รุ่นเก่าอย่างแน่นอน

หากบนแพลตฟอร์มดังกล่าวคุณทำสิ่งที่ชอบ

 find / ... | less

ข้อความแสดงข้อผิดพลาดใด ๆ (เช่นการอนุญาตไดเรกทอรี) ปรากฏเช่นนี้น้อย

 stdout line 1
 stdout line 2
 error message text
 stdout line 4

ดังนั้นบรรทัดเอาต์พุตจะถูกบดบังด้วยข้อความแสดงข้อผิดพลาด

หากคุณรีเฟรชหน้าเพจบรรทัดเอาต์พุตจะแสดงอย่างถูกต้อง แต่คุณสูญเสียข้อความแสดงข้อผิดพลาด เมื่อคุณออกจากหน้าจอน้อยลงจะถูกล้างยกเว้นหน้าจอพร้อมรับคำสั่ง

ถ้าคุณทำสิ่งที่ชอบ

  find / ... 2>&1 | less

ข้อความแสดงข้อผิดพลาดจะถูกรวมเข้ากับเอาต์พุตมาตรฐาน อีกครั้งเมื่อคุณออกน้อยหน้าจอจะว่างเปล่า

หากคุณต้องการตรวจสอบเอาต์พุตมาตรฐานเพียงครั้งแรกให้น้อยลงจากนั้นดูข้อความแสดงข้อผิดพลาดหลังจากออกน้อยกว่าคุณต้องมีวิธีแก้ไขปัญหาอื่น

นั่นคือสิ่งที่ฉันแนะนำอย่างไม่แน่นอนในคำตอบสองบรรทัดดั้งเดิมของฉัน


นี่คือขยะ คำตอบของโจอาคิมควรเป็นคำตอบที่ยอมรับได้
Vanilla Face

2
@VanillaFace: ฉันได้เพิ่มเนื้อหาที่ชัดเจนลงในคำตอบของฉัน
RedGrittyBrick

16

คุณต้องเปลี่ยนเส้นทางstderrไปที่stdout:

$ ./somecommad 2>&1 | less

ตรวจสอบคู่มือเปลือกของคุณ (เช่นman bash)


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

ชวเลขสำหรับ2> & 1คือ| & ดังนั้นจึงสามารถทำให้ง่ายขึ้นเป็น$ ./somecommad |& less
Melvin Abraham

1

เพียงแค่บอกเชลล์ให้เปลี่ยนเส้นทาง fd 2 ไปยัง fd 1 (stderr ถึง stdout)

 make 2>&1 | less

1

สิ่งหนึ่งที่ขาดจากคำตอบทั้งหมดจนถึงขณะนี้คือเหตุผลว่าทำไมสิ่งนี้จึงเกิดขึ้น ปัญหาที่นี่คือสภาพการแข่งขันบางอย่างระหว่างกระบวนการส่งออกข้อมูลไปยังstderrและlessแสดงผลลัพธ์จากstdoutบนเทอร์มินัล หากlessจะเริ่มต้นการแสดงหลังจากที่การส่งออกทั้งหมดเพื่อให้stderrได้รับการตีพิมพ์ไปยังสถานีแล้วจะรักษาที่และคุณสามารถเห็นข้อความหลังจากออกless lessOTOH ถ้าlessเริ่มแสดงเนื้อหาแล้วข้อความแสดงข้อผิดพลาดจะรวมเข้ากับlessเอาต์พุตของและไม่มีอะไรถูกเก็บรักษาไว้หลังจากlessออก (เพราะlessเพียงรักษาเทอร์มินัลเหมือนก่อนที่มันจะเริ่มต้นและไม่รู้อะไรเลยเกี่ยวกับข้อความผิดพลาดที่เข้ามา)

คุณสามารถเห็นได้อย่างง่ายดายถ้าคุณทำเช่น

grep foo -r /etc | less

ข้อความแสดงข้อผิดพลาด "การอนุญาตที่ถูกปฏิเสธ" ทั้งหมดรวมกับlessเอาต์พุตและไม่มีอะไรเกิดขึ้นหลังจากที่คุณออก ถ้าคุณทำ

grep foo -r /etc | (sleep 10; less)

ข้อความแสดงข้อผิดพลาดทั้งหมด (หรืออย่างน้อยที่สุด) ได้รับการพิมพ์ไปยังเครื่องเทอร์มินัลก่อนที่จะlessได้รับโอกาสในการแสดงผลและคุณจะเห็นข้อความแสดงข้อผิดพลาดในภายหลัง

แน่นอนคุณมักจะไม่ต้องการที่จะรอ 10 วินาทีก่อนที่คุณจะเริ่มต้นlessแต่มีลินุกซ์นอกจากนี้คุณยังสามารถจัดหาค่าเศษส่วนสำหรับเวลาที่รอคอยและมีกระบวนการทำงานได้อย่างรวดเร็วมักจะเป็นสิ่งที่น้อยที่สุดเท่าที่sleep 0.1จะเพียงพอที่จะหลีกเลี่ยงสภาพการแข่งขัน (แต่แน่นอนถ้าคุณต้องการหรืออยู่ในด้านที่ปลอดภัยจริงๆให้ใช้โซลูชันของ RedGrittyBrick)


0

คุณต้องเข้าใจแนวคิดของ "file descriptors" โดยปกติแล้วแอปพลิเคชั่น unix จะเริ่มด้วยตัวอธิบายไฟล์พิเศษสามตัว:

  • อินพุตมาตรฐาน
  • เอาต์พุตมาตรฐาน
  • มาตรฐานบกพร่อง

"ไพพ์" |ในเชลล์เชื่อมต่อstdoutจากกระบวนการหนึ่งด้วยกระบวนการstdinถัดไป

ข้อผิดพลาดคือ - โดยการออกแบบ - ไม่ถูกป้อนให้stdinกับกระบวนการถัดไป พวกเขามักจะไม่สมเหตุสมผลกับแอปพลิเคชันถัดไปและไม่ควรซ่อนจากผู้ใช้

หากคุณต้องการที่จะผสมข้อผิดพลาดใน stdout คุณสามารถใช้เช่น2>&1ซึ่งกล่าวเป็นหลัก "ผนวก stderr เพื่อ stdout" ตัวอย่างเช่น

find /etc 2>&1 | less

ควรรวมเอาท์พุทข้อผิดพลาดจากไฟล์ที่ไม่สามารถเข้าถึงได้

find /etc 2>&1 >/dev/null | less

จะให้ข้อผิดพลาดเท่านั้น


0

ฉันสับสนเกี่ยวกับคำถามของคุณเท่าที่ฉันสามารถบอกได้ว่าพฤติกรรมที่คุณต้องการเป็นค่าเริ่มต้น

เมื่อฉันใช้

#include <stdio.h>

int main(int argc, char**argv){
  for (int j=0; j<10; ++j){
    fprintf( (j%2 ? stdout : stderr) , "%d\n" , j);
  }
  return 0;
}

เพื่อรับการทดสอบอย่างง่าย

$ ./testredirection | less

ทำในสิ่งที่คุณถาม นั่นคือฉันเห็น

1
3
5
7
9
(END) 

ในlessและ

$ ./testredirection | less
0
2
4
6
8
$ 

เมื่อฉันออกจาก less


มันแปลก แต่สิ่งต่าง ๆ ไม่ได้เป็นแบบนี้เสมอไป ลองใช้สคริปต์ ( echo info ; echo error 1>&2) และทำซ้ำการทดสอบ: ทั้งสองบรรทัดถูกไพพ์ไปที่น้อยกว่า
cYrus

@ cYrus: มันทำงานได้ตามที่คาดไว้สำหรับฉันเช่นกัน 'หลักสูตรที่ฉันลองในกล่อง Mac OS Bash 3.2.17 น้อยกว่า 394 บางทีลินุกซ์บางอย่างที่เฉพาะเจาะจง ไม่ว่าในกรณีใดวิธีของ RedGrittyBrick ควรจะทำงานได้ดี
dmckee --- ผู้ดูแลอดีตลูกแมว

แปลก! Debian Squeeze / Bash 4.1.5 / น้อยกว่า 436
cYrus

ใช่ฉันเปิดเชลล์ของกล่อง Scientific Linux 5.3 ในที่ทำงานและมีพฤติกรรมตามที่คาดหวังด้วย bash 3.0.15 และต่ำกว่า 382 อาจมีการถดถอยในนั้นหรือไม่
dmckee --- ผู้ดูแลอดีตลูกแมว

ฉันไม่รู้ฉันคิดว่ามันเป็นเพียงเรื่องของการบัฟเฟอร์
cYrus

0

ฉันบังเอิญพบปัญหานี้ใน Debian 5.0 ของฉันเมื่อเร็ว ๆ นี้ ตัวอย่างเช่น ls abc | น้อยฉันพบว่าข้อความแสดงข้อผิดพลาดน้อยลงซึ่งขัดกับความรู้ของฉัน

หลังจากความพยายามฉันพบว่ามันเป็นเพียงบางสิ่งที่เกี่ยวข้องกับบัฟเฟอร์หน้าจอ stderr ไม่ได้ไปน้อยลงจริง คุณสามารถใช้ปุ่มลูกศรขึ้นหรือลง (หรือ j / k) เพื่อสาธิต

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