อะไรคือความแตกต่างระหว่าง `>> / dev / stderr` (ด้วยพื้นที่สีขาว) และ`> & 2`


11

ในทุบตี

ฉันมีปัญหาในการพิจารณาสิ่งที่ฉันควรใช้?

สคริปต์ของฉันทั้งหมดใช้ ">> / dev / stderr"

ที่ bash prompt, ถ้าฉันลอง:
echo test >>/dev/stderrwork
echo test >> /dev/stderrwork
echo test >/dev/stderrworks
echo test > /dev/stderrworks

echo test >>&2ล้มเหลว!
echo test >> &2ล้มเหลว!
echo test >&2ทำงาน
echo test > &2ล้มเหลว!

ฉันยินดีที่จะเปลี่ยนสคริปต์>&2ทั้งหมดเป็น

ดูเหมือนว่าจะมีผลกระทบอย่างมากกับ ssh (หลังจากsu SomeUser) ที่>>/dev/stderrจะไม่ทำงานเลย (ปฏิเสธสิทธิ์) เพียง>&2จะทำงาน


คุณสามารถแสดงตัวอย่างของข้อผิดพลาด ssh ได้หรือไม่ ฉันทำซ้ำไม่ได้
Jeff Schaller

@JeffSchaller คุณถูกต้องมันเป็นหลังจากsuที่ปัญหาเกิดขึ้นอัปเดตคำถาม
Aquarius Power

@AquariusPower, ... เพื่ออธิบายความแตกต่างดังกล่าวโดยวิธีการ: ด้วยsu -c 'some command', คำสั่งนั้นดำเนินการโดย/bin/sh, ไม่bash, ดังนั้นพฤติกรรมเฉพาะ bash (เช่นการจำลอง/dev/stderrเพื่อการเปลี่ยนเส้นทางเมื่อไม่มี) ไม่รับประกันว่าจะมีอยู่
Charles Duffy

คำตอบ:


22

>& nเป็นไวยากรณ์ของเชลล์เพื่อทำซ้ำไฟล์ descriptorโดยตรง ตัวอธิบายไฟล์ 2 คือ stderr; นั่นเป็นวิธีที่ทำงาน คุณสามารถทำซ้ำ descriptor ไฟล์อื่นได้เช่นกันไม่ใช่แค่ stderr คุณไม่สามารถใช้โหมดผนวกได้ที่นี่เนื่องจากการทำซ้ำตัวให้คำอธิบายไฟล์ไม่เคยตัดทอน (แม้ว่า stderr ของคุณจะเป็นไฟล์) และ>&เป็นโทเค็นเดียวนั่นคือสาเหตุที่คุณไม่สามารถเว้นช่องว่างข้างใน แต่ใช้>& 2งานได้

>> nameเป็นไวยากรณ์ที่ได้รับอนุญาตที่แตกต่างกันโดยที่nameชื่อไฟล์ (และโทเค็นคือ>>) ในกรณีนี้คุณใช้ชื่อไฟล์/dev/stderrซึ่งโดยการจัดการเฉพาะระบบปฏิบัติการ (บน Linux เป็น symlink ไป/proc/self/fd/2) ก็หมายถึงข้อผิดพลาดมาตรฐาน ผนวกและตัดทอนโหมดทั้งปิดท้ายการทำสิ่งเดียวกันเมื่อ stderr เป็นเทอร์มินัลเนื่องจากไม่สามารถตัดทอนได้ หากข้อผิดพลาดมาตรฐานของคุณเป็นไฟล์อย่างไรก็ตามมันจะถูกตัดทอน:

anthony@Zia:~$ bash -c 'echo hi >/dev/stderr; echo bye >/dev/stderr' 2>/tmp/foo
anthony@Zia:~$ cat /tmp/foo
bye

หากคุณเห็นข้อผิดพลาดกับ/dev/stderrover ssh อาจเป็นไปได้ว่าผู้ดูแลระบบเซิร์ฟเวอร์ได้ใช้มาตรการรักษาความปลอดภัยบางอย่างเพื่อป้องกันไม่ให้ symlink นั้นทำงาน (เช่นคุณไม่สามารถเข้าถึง/procหรือ/dev) ในขณะที่ฉันคาดหวังว่าจะทำให้เกิดการแตกแปลกทุกประเภทการใช้ไวยากรณ์ตัวอธิบายไฟล์ซ้ำกันเป็นวิธีที่เหมาะสมอย่างสมบูรณ์ (และน่าจะมีประสิทธิภาพมากกว่าเล็กน้อย) ส่วนตัวฉันชอบมัน


ฉันมีปัญหาใหญ่ในการพยายามทำซ้ำปัญหาที่ถูกตัดทอนที่ฉันเคยมีมาก่อน (ไม่อย่างนั้นฉันจะเพิ่มคำถามนั้นไปที่ฮิเฮ) เหตุผลที่ฉันเปลี่ยนทุกอย่างเพื่อใช้งาน>>ขอบคุณที่ชี้ให้เห็น! นอกจากนี้ฉันพลาดขั้นตอนsu SomeUserหลังจากเชื่อมต่อผ่าน ssh
กุมภ์กุมภ์

สิ่งนี้bash -c 'echo hi >&2; echo bye >&2' 2>/tmp/foo;cat /tmp/fooจะไม่ถูกตัดทอน! (แม้จะมี2>&1 |tee /tmp/foo) >&2สิ่งที่เป็นที่สมบูรณ์แบบสำหรับการเข้าสู่ระบบและจะทำงานได้อย่างสมบูรณ์หลังจากที่ผมเปลี่ยนทุกอย่างให้ ดังนั้นฉันเดาว่ามีเพียงการใช้งานไฟล์โดยตรงเท่านั้นที่/dev/stderrอนุญาตให้ตัดทอนไม่ใช่ตัวบ่งชี้ซ้ำซ้อนขอบคุณมาก!
กุมภ์กุมภ์

@AquariusPower คำอธิบายไฟล์ที่ถูกต้องซ้ำกันไม่เคยตัดทอน นั่นคือในวรรคแรกฉันอาจจะต้องเน้นมันอย่างใด
Derobert

ไม่จำเป็นฉันช้าบางครั้ง ehehe
Aquarius Power

3
คำตอบนี้สามารถปรับปรุงได้ > & เป็นโทเค็นเดียวไม่ใช่สองและมีความสับสนของ OP อยู่
โจชัว

8

กรณีความล้มเหลวเกิดขึ้นเนื่องจากไวยากรณ์ของ bashสำหรับใช้&ในการเปลี่ยนเส้นทางระบุหนึ่ง>และต้องการให้มีอยู่ติดกับ&เครื่องหมายโดยตรง:

[N]> & คำ


2

ใช้'>'เพื่อเปลี่ยนเส้นทาง (ตัดถ้ามี) หรือ'>>'(ต่อท้ายหากมี)

ใช้'>&'เพื่อทำซ้ำกระแสตัวอย่างเช่นถ้าคุณต้องการข้อผิดพลาดมาตรฐานและออกมาตรฐานในไฟล์เดียวกันคุณเปลี่ยนเส้นทางไปยังไฟล์'> output.log'และข้อผิดพลาดด้วย'2>&'

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