“ ไม่พบคำสั่ง” เมื่อฟังก์ชั่น sudo'ing จาก ~ / .zshrc


10

ฉันมีฟังก์ชั่นใน~/.zshrc:

findPort() {
    lsof -t -i :$1
}

findPort 3306ภาวนาตามปกติคือ

ฉันต้องการเรียกใช้ด้วยสิทธิ์ระดับสูง แต่ฉันได้รับ "ไม่พบคำสั่ง"

  git 🍔 sudo findPort 3306
sudo: findPort: command not found

ผมเข้าใจเหตุผลก็คือผู้ใช้รากทั้งวิ่งเป็นเปลือกไม่โต้ตอบ (จึงไม่ได้หมายถึง .zshrc) หรือหมายถึงแตกต่างกัน .zshrc

ฉันได้เห็นคำถามที่คล้ายกันเกี่ยวกับaliasแต่ไม่มีคำถามเกี่ยวกับฟังก์ชั่นที่ผู้ใช้กำหนด คำตอบสำหรับปัญหานี้aliasเกี่ยวข้องกับการเพิ่มนามแฝงไปที่~/.zshrc:

alias sudo='nocorrect sudo '

หรือบางที:

alias sudo='sudo '

ฉันลองทั้งสองวิธีแล้วและปัญหายังคงมีอยู่ (ใช่ฉันเปิดตัวเชลล์ใหม่)

ฉันได้ลองใช้งานsudo chshเพื่อให้แน่ใจว่าเชลล์รูทของฉันทำงานzshได้ ไม่มีวิธีการแก้ปัญหาเหล่านี้ลบปัญหา "คำสั่งไม่พบ"

มีวิธีเรียกใช้ฟังก์ชันที่ผู้ใช้กำหนดเองภายใต้ sudo หรือไม่


ดูเพิ่มเติมที่: unix.stackexchange.com/questions/181414/ … (ไม่ตั้งค่าสถานะเนื่องจาก zsh มีลูกเล่นของตัวเอง)
muru

คำตอบ:


13

sudoรันคำสั่งโดยตรงไม่ใช่ผ่านเชลล์และแม้ว่ามันจะรันเชลล์เพื่อรันคำสั่งนั้นมันจะเป็นการเรียกเชลล์ใหม่และไม่ใช่อันที่อ่านของคุณ~/.zshrc(แม้ว่ามันจะเริ่มเชลล์แบบโต้ตอบก็อาจอ่านrootได้~/.zshrcไม่ใช่ของคุณเว้นแต่คุณได้กำหนดค่าsudoให้ไม่รีเซ็ต$HOMEตัวแปร)

ที่นี่คุณจะต้องบอกsudoให้เริ่มzshเปลือกใหม่และบอกzshให้อ่าน~/.zshrcก่อนที่จะเรียกใช้ฟังก์ชัน:

sudo zsh -c '. $0; "$@"' ~/.zshrc findPort 3306

หรือ:

sudo zsh -c '. $0; findPort 3306' ~/.zshrc

หรือเพื่อแบ่งปันฟังก์ชั่น zsh ปัจจุบันของคุณกับสิ่งที่zshเรียกใหม่โดยsudo:

sudo zsh -c "$(functions); findPort 3306"

แม้ว่าคุณจะได้รับรายการ ARGผิดพลาดนานเกินไปหากคุณมีฟังก์ชั่นจำนวนมากที่กำหนดไว้ (เช่นเมื่อใช้ระบบเสร็จสิ้น) ดังนั้นคุณอาจต้องการ จำกัด ให้findPortฟังก์ชัน (และฟังก์ชั่นอื่น ๆ ทุกมันอาศัยถ้ามี):

sudo zsh -c "$(functions findPort); findPort 3306"

คุณสามารถทำได้:

sudo zsh -c "(){$functions[findPort]} 3306"

เพื่อฝังโค้ดของfindPortฟังก์ชันในฟังก์ชันที่ไม่ระบุตัวตนซึ่งคุณผ่านอาร์กิวเมนต์ 3306 หรือแม้กระทั่ง:

sudo zsh -c "$functions[findPort]" findPort 3306

(สคริปต์แบบอินไลน์ผ่านไป-c เป็นร่างกายของฟังก์ชั่น)

คุณสามารถใช้ฟังก์ชันตัวช่วยเช่น:

zsudo() sudo zsh -c "$functions[$1]" "$@"

ไม่ได้ใช้:

sdo () {sudo zsh -c "() {$ ฟังก์ชั่น [$ 1]} $ {@: 2}"}

ในฐานะที่เป็นข้อโต้แย้งของsdoจะได้รับการแยกในระดับอื่นของเชลล์ เปรียบเทียบ:

$ e() echo "$@"
$ sdo e 'tname;uname'
tname
Linux
$ zsudo e 'tname;uname'
tname;uname

sudoฉันจำเป็นต้องใช้วิธีการแก้ปัญหาที่สั้นที่สุดเท่าที่พิมพ์ ฉันสามารถปรับแก้ปัญหาฟังก์ชั่นที่ไม่ระบุชื่อของคุณเพื่อทำสิ่งนั้นได้ ฉันได้เพิ่มฟังก์ชั่นต่อไปนี้ใน my ~/.zshrcซึ่งเป็นฟังก์ชั่นในการใช้งานฟังก์ชั่นอื่น ๆ ที่มีสิทธิ์ยกระดับ:sdo() { sudo zsh -c "(){$functions[$1]} ${@:2}" }
Birchlabs

1
@ Birchlabs ดูการแก้ไข
Stéphane Chazelas

ขอบคุณ; ฉันได้อัปเดตคำตอบเพื่อใช้ทางลัดใหม่ที่คุณเสนอ
Birchlabs

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

3

วิธีแก้ปัญหาที่ง่ายมากสำหรับฉันคือการเรียกใช้เชลล์แบบโต้ตอบโดยใช้sudo -sซึ่งดูเหมือนว่าจะทำงานกับ zsh เวอร์ชัน 5.2 ที่มาพร้อมกับ macOS ของฉัน ~/.zshrcนี้จะให้ฉันด้วยฟังก์ชั่นจากฉัน

จาก manudo ของ sudo ซึ่งไม่ได้บอกใบ้ถึงพฤติกรรมนี้:

-s, - เชลล์
เรียกใช้เชลล์ที่ระบุโดยตัวแปรสภาวะแวดล้อม SHELL หากมีการตั้งค่าหรือเชลล์ที่ระบุโดยรายการฐานข้อมูลรหัสผ่านของผู้ใช้ที่เรียกใช้ หากระบุคำสั่งคำสั่งจะถูกส่งไปยังเชลล์เพื่อดำเนินการผ่านตัวเลือกเชลล์ของ -c หากไม่ได้ระบุคำสั่งเชลล์เชิงโต้ตอบจะถูกดำเนินการ

ฉันไม่แน่ใจว่ากรณีการใช้งานของคุณคืออะไร แต่ฉันสงสัยว่าคุณกำลังมองหาโซลูชันแบบโต้ตอบ


มันใช้งานได้จริง แม้ว่ามันจะไม่ใช่กระบวนการทำงานที่ฉันมีอยู่ในใจ ความปรารถนาของฉันคือการคงอยู่ในทันทีในฐานะผู้ใช้ปกติของฉันและยกระดับฟังก์ชั่นที่ผู้ใช้กำหนดmyFuncโดยพิมพ์sudo myFunc- วิธีเดียวกับที่ฉันจะยกระดับกระบวนการใด ๆ (เช่นsudo rm -rf .) โซลูชันนี้ยกระดับพรอมต์ทั้งหมดของฉันและฟังก์ชั่นในอนาคตทั้งหมดรวมถึงการเปลี่ยนผู้ใช้ของฉันสำหรับฟังก์ชั่นในอนาคตทั้งหมด - ซึ่งเกินความจริงเล็กน้อย
Birchlabs

sudo -sคำสั่งจะเปิดตัวอย่างของเปลือกของคุณอีกใช้ super หากคุณรันคำสั่งนั้นแบบโต้ตอบเชลล์ใหม่ของคุณจะเป็นแบบโต้ตอบ แต่คำสั่งsudo -s findPort 3306จะเรียกใช้คำสั่งfindPort 3306ในเชลล์ของคุณเป็น superuser จากนั้นออกด้วยรหัสสถานะของคำสั่งนั้น
Damien Flament

2

ผมสามารถที่จะผลิตนำมาใช้ใหม่จดชวเลขหนึ่งของการแก้ปัญหาที่อธิบายไว้ในStéphane Chazelas' คำตอบ [แก้ไข: Stéphaneทำซ้ำบนทางลัดเดิมที่ฉันเสนอ รหัสอธิบายที่นี่เป็นรุ่นที่ใหม่กว่าของเขาทำ]

ใส่สิ่งนี้ลงใน~/.zshrc:

sdo() sudo zsh -c "$functions[$1]" "$@"

ตอนนี้คุณสามารถใช้sdoเป็น " sudoสำหรับฟังก์ชั่นที่ผู้ใช้กำหนดเท่านั้น"

เพื่อยืนยันว่าใช้sdoงานได้: คุณสามารถลองใช้ฟังก์ชั่นที่ผู้ใช้กำหนดเองซึ่งพิมพ์ชื่อผู้ใช้ของคุณ

 birch@server ~/ 🍔 test() whoami

 birch@server ~/ 🍔 test
birch

 birch@server ~/ 🍔 sdo test
root

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