bash: / dev / stderr: การอนุญาตถูกปฏิเสธ


19

หลังจากอัปเกรดเป็นเวอร์ชั่นใหม่แล้วbashสคริปต์ของฉันก็เริ่มพ่นข้อผิดพลาด:

bash: /dev/stderr: Permission denied

ในเวอร์ชันก่อนหน้า Bash จะจำชื่อไฟล์เหล่านั้นได้ภายใน (ซึ่งเป็นสาเหตุที่คำถามนี้ไม่ซ้ำกับของไฟล์นี้ ) และทำสิ่งที่ถูกต้อง (tm)อย่างไรก็ตามสิ่งนี้หยุดทำงานทันที ฉันจะทำอย่างไรจึงจะสามารถเรียกใช้สคริปต์ของฉันอีกครั้งได้สำเร็จ

ฉันได้ลองเพิ่มผู้ใช้ที่เรียกใช้สคริปต์ไปยังกลุ่มttyแต่มันก็ไม่ได้ทำให้แตกต่าง (แม้หลังจากออกจากระบบแล้ว)

ฉันสามารถทำซ้ำนี้ในบรรทัดคำสั่งโดยไม่มีปัญหา:

$ echo test > /dev/stdout
bash: /dev/stdout: Permission denied
$ echo test > /dev/stderr
bash: /dev/stderr: Permission denied
$ ls -l /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stdout -> /proc/self/fd/1
$ ls -lL /dev/stdout /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stdout
$ echo $BASH_VERSION
4.2.24(1)-release

บนระบบเก่า (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release

1
อะไรคือผลลัพธ์ของls -l /dev/stdout /dev/stderrและls -lL /dev/stdout /dev/stderr?
Keith Thompson

@Keith: ดูคำถามที่แก้ไขแล้วของฉัน นั่นหมายความว่า Bash ได้ละทิ้งการจัดการภายในอย่างสมบูรณ์หรือไม่? ในระบบที่เก่ากว่าสัญลักษณ์เหล่านี้ไม่มีอยู่และรหัสก็ใช้ได้โดยไม่มีปัญหา โปรดทราบว่านี่คือการแอบอ้างผ่านsudo su username2 -...
0xC0000022L

คุณกำลังใช้เวอร์ชันทุบตีอะไร echo $BASH_VERSION
jippie

1
รุ่นเก่าและใหม่มีรุ่นอะไรบ้าง (ก่อนและหลังระบบปฏิบัติการของคุณและทุบตี?
Keith Thompson

คำตอบ:


41

ผมไม่คิดว่านี่คือทั้งหมดเป็นปัญหาทุบตี

ในความคิดเห็นคุณบอกว่าคุณเห็นข้อผิดพลาดนี้หลังจากทำ

sudo su username2

usernameเมื่อเข้าสู่ระบบเป็น มันคือสิ่งsuที่ก่อให้เกิดปัญหา

/dev/stdoutเป็น symlink ไป/proc/self/fd/1ซึ่งเป็น symlink /dev/pts/1ไปสำหรับตัวอย่างเช่น /dev/pts/1ซึ่งเป็น pseudoterminal เป็นเจ้าของและเขียนได้โดย, username; ความเป็นเจ้าของนั้นได้รับเมื่อusernameเข้าสู่ระบบเมื่อคุณsudo su username2ความเป็นเจ้าของ/dev/pts/1จะไม่เปลี่ยนแปลงและusername2ไม่มีสิทธิ์ในการเขียน

ฉันขอยืนยันว่านี่เป็นข้อผิดพลาด /dev/stdout ควรเป็นนามแฝงสำหรับเอาต์พุตสตรีมมาตรฐาน แต่ที่นี่เราเห็นสถานการณ์ที่ใช้echo helloงานได้ แต่echo hello > /dev/stdoutล้มเหลว

วิธีแก้ปัญหาหนึ่งคือการทำให้username2สมาชิกของกลุ่มttyแต่ที่จะให้username2สิทธิ์ในการเขียนถึงtty ใด ๆซึ่งอาจไม่พึงประสงค์

วิธีแก้ปัญหาอีกก็จะไปเข้าสู่ระบบไปยังusername2บัญชีแทนที่จะใช้suเพื่อให้/dev/stdoutชี้ไปยัง pseudoterminal username2จัดสรรใหม่เป็นเจ้าของโดย สิ่งนี้อาจไม่สามารถใช้งานได้จริง

วิธีแก้ปัญหาอื่นคือแก้ไขสคริปต์ของคุณเพื่อไม่ให้อ้างอิง/dev/stdoutและ/dev/stderr; ตัวอย่างเช่นแทนที่สิ่งนี้:

echo OUT > /dev/stdout
echo ERR > /dev/stderr

โดยสิ่งนี้:

echo OUT
echo ERR 1>&2

ฉันเห็นสิ่งนี้ในระบบของฉันเอง Ubuntu 12.04 กับ bash 4.2.24 - แม้ว่าเอกสาร bash ( info bash) ในระบบของฉันจะบอกว่า/dev/stdoutและ/dev/stderrได้รับการดูแลเป็นพิเศษเมื่อใช้ในการเปลี่ยนเส้นทาง แต่แม้ว่า bash จะไม่ปฏิบัติต่อชื่อเหล่านั้นเป็นพิเศษ แต่ก็ควรทำหน้าที่เทียบเท่ากับสตรีม I / O มาตรฐาน (POSIX ไม่ได้กล่าวถึง/dev/std{in,out,err}ดังนั้นอาจเป็นการยากที่จะโต้แย้งว่านี่เป็นข้อบกพร่อง)

เมื่อดูที่ทุบตีรุ่นเก่าเอกสารแสดงนัยว่า/dev/stdoutet al ได้รับการดูแลเป็นพิเศษไม่ว่าจะมีไฟล์อยู่หรือไม่ก็ตาม คุณลักษณะถูกนำมาใช้ใน bash 2.04 และNEWSไฟล์สำหรับรุ่นนั้นบอกว่า:

รหัสการเปลี่ยนเส้นทางตอนนี้จัดการชื่อไฟล์หลายชื่อเป็นพิเศษ: / dev / fd / N, / dev / stdin, / dev / stdout และ / dev / stderr ไม่ว่าจะมีอยู่ในระบบไฟล์หรือไม่

แต่ถ้าคุณตรวจสอบซอร์สโค้ด ( redir.c) คุณจะเห็นว่ามีการเปิดใช้การจัดการพิเศษเฉพาะเมื่อHAVE_DEV_STDINมีการกำหนดสัญลักษณ์(ซึ่งจะถูกกำหนดเมื่อ bash ถูกสร้างจากซอร์ส)

เท่าที่ฉันสามารถบอกได้ว่าไม่มีการทุบตีรุ่นที่ปล่อยออกมาเป็นการจัดการแบบพิเศษของ/dev/stdoutet al โดยไม่มีเงื่อนไข - เว้นแต่การแจกจ่ายบางอย่างได้ทำการแก้ไขแล้ว

ดังนั้นวิธีแก้ปัญหาอื่น (ซึ่งฉันไม่ได้ลอง) ก็คือการคว้าแหล่งทุบตีแก้ไขredir.cเพื่อให้การ/dev/*จัดการพิเศษโดยไม่มีเงื่อนไขและใช้เวอร์ชันที่สร้างใหม่ของคุณแทนที่จะเป็นรุ่นที่มาพร้อมกับระบบของคุณ นี่อาจจะเกินความจริงได้

สรุป :

ระบบปฏิบัติการของคุณเช่นเหมืองไม่ได้จัดการกรรมสิทธิ์และสิทธิ์ของ/dev/stdoutและ/dev/stderrถูกต้อง ทุบตีควรปฏิบัติต่อชื่อเหล่านี้เป็นพิเศษในการเปลี่ยนเส้นทาง แต่ในความเป็นจริงมันจะทำเช่นนั้นเฉพาะในกรณีที่ไม่มีไฟล์ ที่จะไม่สำคัญว่า/dev/stdoutและ/dev/stderrทำงานอย่างถูกต้อง ปัญหานี้จะปรากฏขึ้นเมื่อคุณsuไปยังบัญชีอื่นหรือทำสิ่งที่คล้ายกัน หากคุณเพียงแค่ลงชื่อเข้าใช้บัญชีการอนุญาตนั้นถูกต้อง


ความเป็นเจ้าของของ TTY ควรเปลี่ยนไป นั่นคือสิ่งที่ ConsoleKit (หรือที่รู้จักกันในชื่อpam_ck_connector.so)
มิเคล

ที่จริงฉันอาจผิด จะต้องขุดอีก
มิเคล

ในระบบของฉัน/proc/self/fd/1มีการปรับปรุงการอนุญาต แต่ไม่มีประโยชน์เพราะมันเป็น symlink เกิดขึ้นกับ Fedora ด้วยซึ่งดูเหมือนว่าจะตัดทอน ConsoleKit
มิเคล

1

ที่จริงแล้วเหตุผลสำหรับเรื่องนี้คือ udev ตั้งค่าการอนุญาตเป็น 0620 บนอุปกรณ์ tty โดยเฉพาะและ su ไม่ได้เปลี่ยนความเป็นเจ้าของหรือการอนุญาตไม่ควร ในมุมมองของฉันสิ่งนี้ทำให้เราอยู่ในสถานการณ์ที่ทำให้ / dev / std * ไม่สามารถพกพาได้

ทางออกที่ง่ายคือการใส่ "mesg y" ใน / etc / profile (หรือโปรไฟล์ระดับบนสุดที่คุณต้องการใช้) เนื่องจากการเปลี่ยนแปลงนี้จะอนุญาตให้คุณใช้อุปกรณ์ tty เป็น 0622 ฉันไม่ชอบมัน แต่มันอาจจะดีกว่า กว่าการเปลี่ยนกฎ udev


"msg y" ไม่ทำงาน
Luciano

รอสักครู่ ... อาจค้นหาBash ที่จัดการชื่อไฟล์หลาย ๆ ชื่อเป็นพิเศษเมื่อพวกมันถูกใช้ในการเปลี่ยนเส้นทางในหน้า man ของ Bash
0xC0000022L

0

ในฐานะที่เป็นผู้ใช้ลีนุกซ์มานานฉันเพิ่งติดตั้งระบบ Ubuntu 64 บิต 12.04 LTS ใหม่และได้รับการประหลาดใจว่าทำไมทุบตีสคริปต์ของฉันไม่ทำงาน - ถูกปฏิเสธสิทธิ์ - และต่อมาฉันก็พบกระทู้นี้ ฉันคิดว่าปัญหาอาจเกิดจากบางสิ่งในระบบปฏิบัติการใหม่

ในท้ายที่สุดปรากฎว่าฉันใช้เครื่องมือ UI เพื่อตั้งค่าการอนุญาตใน/homeไดเรกทอรีของฉันอย่างน่างงงวยและปัญหานั้นเกี่ยวข้องกับไดรฟ์ เพื่อให้แน่ใจว่าฉันสร้างtempไดเรกทอรีใน/optและพบว่าสคริปต์ของฉันจะทำงานได้ดีจากที่นั่น เมื่อฉันแก้ไข/homeสิทธิ์ของไดรฟ์ทุกอย่างก็กลับเป็นปกติ

แก้ปริศนาเล็ก ๆ น้อย ๆ ได้ ถอนหายใจ


2
สิ่งนี้จะต้องเป็นข้อผิดพลาดที่แตกต่างกัน การแก้ไขบางสิ่งใน / home ไม่มีผลกับ / dev
ott--

-1

นี่เป็นคำถามเก่า แต่ฉันคิดว่ายังคงมีความเกี่ยวข้องมากดังนั้นนี่คือวิธีแก้ปัญหาที่ฉันพบซึ่งไม่ได้กล่าวถึงที่นี่

ฉันเจอคำถามนี้เพราะฉันยังเห็นปัญหาใน 'su' เปลี่ยนบัญชีคำสั่งดำเนินการเช่นนี้ในทุบตี:

echo test > /dev/stderr

เนื่องจากสิ่งที่ฉันพยายามจะทำคือเปลี่ยนเส้นทาง stdout ไปยัง stderr ต่อไปนี้จะได้ผลเหมือนกันและใช้งานได้แม้ในบัญชีที่เปลี่ยนเป็น 'su':

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