ในฐานะที่เป็น@dessert อธิบายปัญหาที่นี่เป็นที่สคริปต์ของคุณไม่ได้มีสาย shebang โดยไม่ต้อง shebang ที่จะเริ่มต้นกับความพยายามที่จะเรียกใช้ไฟล์โดยใช้sudo
/bin/sh
ฉันไม่พบเอกสารใด ๆ เลย แต่ฉันยืนยันด้วยการตรวจสอบsudo
ซอร์สโค้ดที่ฉันพบสิ่งต่อไปนี้ในไฟล์pathnames.h
:
#ifndef _PATH_BSHELL
#define _PATH_BSHELL "/bin/sh"
#endif /* _PATH_BSHELL */
ซึ่งหมายความว่า "ตั้งค่าหาก_PATH_BSHELL
ไม่ได้กำหนดตัวแปรตั้งเป็น/bin/sh
" จากนั้นในconfigure
สคริปต์ที่รวมอยู่ใน tarball แหล่งที่มาเรามี:
for p in "/bin/bash" "/usr/bin/sh" "/sbin/sh" "/usr/sbin/sh" "/bin/ksh" "/usr/bin/ksh" "/bin/bash" "/usr/bin/bash"; do
if test -f "$p"; then
found=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $p" >&5
$as_echo "$p" >&6; }
cat >>confdefs.h <<EOF
#define _PATH_BSHELL "$p"
EOF
break
fi
done
วงนี้จะมองหา/bin/bash
, /usr/bin/sh
, /sbin/sh
, /usr/sbin/sh
หรือ/bin/ksh
แล้วชุด_PATH_BSHELL
ไปแล้วแต่จำนวนใดจะถูกค้นพบครั้งแรก เนื่องจาก/bin/sh
เป็นครั้งแรกในรายการและมันมีอยู่แล้วมีการตั้งค่า_PATH_BSHELL
/bin/sh
ผลลัพธ์ของสิ่งนี้คือเชลล์เริ่มต้นของsudo
นอกจากจะกำหนดไว้เป็น/bin/sh
อย่างอื่น
ดังนั้นsudo
จะเริ่มต้นกับการรันสิ่งต่าง ๆ ที่ใช้/bin/sh
และบน Ubuntu นั่นคือ symlink dash
ซึ่งเป็นเชลล์ที่สอดคล้องกับ POSIX น้อยที่สุด:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 27 2015 /bin/sh -> dash
[[
สร้างเป็นคุณลักษณะทุบตีมันไม่ได้ถูกกำหนดโดยมาตรฐาน POSIX และไม่เป็นที่เข้าใจโดยdash
:
$ bash -c '[[ true ]] && echo yes'
yes
$ dash -c '[[ true ]] && echo yes'
dash: 1: [[: not found
ในรายละเอียดในการร้องขอทั้งสามที่คุณได้ลอง:
./test.sh
ไม่sudo
; ในกรณีที่ไม่มีบรรทัด Shebang เชลล์ของคุณจะพยายามเรียกใช้งานไฟล์เอง เมื่อคุณใช้งานbash
สิ่งนี้จะทำงานbash ./test.sh
และทำงานอย่างมีประสิทธิภาพ
sudo su
./test.sh
ตามมาด้วย
root
ที่นี่คุณจะเริ่มต้นเปลือกใหม่สำหรับผู้ใช้ นี่จะเป็นสิ่งที่เชลล์กำหนดไว้ใน$SHELL
ตัวแปรสภาพแวดล้อมสำหรับผู้ใช้นั้นและบน Ubuntu เชลล์เริ่มต้นของรูทคือbash
:
$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
sudo ./test.sh
ที่นี่คุณจะปล่อยให้sudo
รันคำสั่งโดยตรง ตั้งแต่เริ่มต้นเปลือกของมันจะถูก/bin/sh
ตามที่อธิบายไว้ข้างต้นนี้ทำให้เกิดการเรียกใช้สคริปต์ด้วย/bin/sh
ซึ่งเป็นdash
และจะล้มเหลวเนื่องจากไม่เข้าใจdash
[[
หมายเหตุ : รายละเอียดของวิธีการsudo
ตั้งค่าเปลือกเริ่มต้นดูเหมือนจะซับซ้อนกว่าเล็กน้อย ฉันพยายามเปลี่ยนไฟล์ที่กล่าวถึงในคำตอบของฉันให้ชี้ไปที่/bin/bash
แต่sudo
ยังคงเป็นค่า/bin/sh
เริ่มต้น ดังนั้นจะต้องมีสถานที่อื่น ๆ ในซอร์สโค้ดที่เชลล์เริ่มต้นถูกกำหนดไว้ อย่างไรก็ตามประเด็นหลัก (ที่เป็นsudo
ค่าเริ่มต้นsh
) ยังคงอยู่
sudo su
เพียงแค่เรียกใช้sudo -i
หรือsudo -s
แทน