ดำเนินการบรรทัดคำสั่งด้วยหนึ่ง sudo


21

ตัวอย่างเช่นถ้าฉันต้องการสร้างไฟล์และป้อนข้อความในหนึ่งบรรทัดฉันสามารถเปลี่ยนเส้นทางผลลัพธ์ไปยังไฟล์ด้วยการใช้>โอเปอเรเตอร์:

echo "something" > /path/foobar

แต่ถ้าฉันไม่มีสิทธิ์เข้าถึงโฟลเดอร์/path/และต้องการสิทธิ์ sudo ฉันจะทำคำสั่งนี้ให้เหมือนกับผู้ใช้ปกติที่มีสิทธิ์ sudo ได้อย่างไร

ฉันเหนื่อย

sudo echo "something" > /path/foobar

แต่นั่นไม่ได้ผลเพราะ sudo นับeditแต่เท่านั้น แต่ไม่ใช่สำหรับส่วนที่ถูกต้อง
ของ>

แน่นอนว่าฉันสามารถรูทก่อนด้วยsudo suหรือใช้teeแทน:

echo "something" | sudo tee /path/foobar

แต่ฉันต้องการหาวิธีแก้ปัญหาที่ฉันสามารถทำงานกับบรรทัดสุดท้ายแทนผ่าน

sudo !!

ไม่มีทางที่จะ "รีไซเคิล" บรรทัดสุดท้ายและเพิ่มsudoข้างหน้าใช่ไหม



สิ่งนี้ไม่ซ้ำกัน ฉันแยก Qeustion จริงและเปลี่ยนชื่อ ตอนนี้เป็นสิ่งที่ฉันกำลังมองหาจริงๆ
rubo77

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

คำตอบ:


13

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

sudo bash -c !!

ยกเว้นว่ามันจะไม่ได้ผลเพราะ!!interpolates ข้อความของคำสั่งก่อนหน้าอักขระพิเศษและทั้งหมด shคุณจำเป็นต้องดึงข้อความของคำสั่งเป็นสตริงและผ่านที่เป็นอาร์กิวเมนต์ไปยัง โชคดีที่fcbuiltinของ bash ช่วยให้คุณทำเช่นนั้นได้¹

sudo bash -c "$(fc -ln -1)"

หรือแม้กระทั่งเพื่อให้แน่ใจว่าได้เรียกใช้ bash รุ่นเดียวกันที่ใช้งานอยู่ในปัจจุบัน:

sudo "$BASH" -c "$(fc -ln -1)"

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

command²เดียวกันทำงานใน zsh และ ksh แม้ว่า ATT ksh93 ต้องการทั้งfirstและlastหมายเลขที่จะส่งผ่านไปยังfc³ (ซึ่งยังใช้งานได้ใน bash, zsh และ pdksh / mksh):

sudo zsh -c "$(fc -ln -1)"
sudo ksh -c "$(fc -ln -1 -1)"
sudo "$0" -c "$(fc -ln -1 -1)"

การใช้$0เพื่อกำหนดความสามารถในการเรียกใช้งานของเชลล์ที่ทำงานอยู่จะทำงานต่อเมื่อเชลล์ถูกเรียกใช้ผ่าน $ PATH และ $ PATH จะไม่เปลี่ยนแปลงหรือผ่านเส้นทางแบบสัมบูรณ์

นี่เป็นอีกวิธีใน zsh ซึ่งชัดเจนกว่าเล็กน้อย แต่นานกว่า:

sudo zsh -c $history[$[HISTCMD-1]]

คำเตือนขั้นสุดท้าย: sudoสำหรับคำสั่งที่อาจเป็นอันตราย อย่าทำให้ง่ายเกินไปที่จะใช้!

¹ มีช่องว่างพิเศษบางอย่างในตอนเริ่มต้นและการทดแทนคำสั่งจะตัดการขึ้นบรรทัดใหม่ในตอนท้าย แต่ไวยากรณ์ของเชลล์ไม่สนใจเรื่องนั้น
² ฉันไม่คิดว่า zsh หรือ ksh มีอะไรอย่าง bash's $BASH; $0ใช้งานได้เฉพาะเมื่อเป็นพา ธ สัมบูรณ์หรือเมื่อไม่มีสแลชและพา ธ การค้นหาคำสั่งจะไม่เปลี่ยนแปลง
³ เป็นชื่อแทนใน ATT ksh แต่นั่นก็ดีเหมือนกัน fchist


9

หากคุณต้องการที่จะทำซ้ำคำสั่งเดียวกันกับsudo !! หลังจากทำคำสั่งเช่นนี้:

echo "something">/path/file

คุณใช้ไวยากรณ์แทนที่ทั่วโลกเพื่อเรียกคืนคำสั่ง:

!!:gs/>/|sudo tee -a /

ใช้ช่องว่างหลังพารามิเตอร์-a

นี่เทียบเท่ากับsudo !! แต่ช่วยให้คุณหลีกเลี่ยงข้อ จำกัด sudo สำหรับ <และ> เพราะ sudo ไม่อนุญาตให้คุณใช้ [<,>]


หากต้องการข้ามข้อ จำกัด sudo โดยทั่วไปสำหรับการเปลี่ยนเส้นทางคุณสามารถใช้สิ่งนี้:

echo "something" | sudo tee myfile

คำสั่ง tee จะอนุญาตให้คุณอ่านจากอินพุตมาตรฐานและเขียนไปยังเอาต์พุตและไฟล์มาตรฐาน

หากคุณต้องการทำซ้ำคำสั่งและเพิ่มข้อความต่อท้ายไฟล์คำสั่ง tee มีอ็อพชัน-aสำหรับการต่อท้าย ดังนั้นคุณสามารถเรียกคืนคำสั่งด้วย

sudo !!

และข้อความจะถูกต่อท้ายในไฟล์

ตัวอย่าง:

echo "something" | sudo tee -a /path/file
sudo !!

ทางออกที่ดี แต่ค่อนข้างยากที่จะจำ ฉันจะสร้างนามแฝงสำหรับคำสั่งโดยใช้ !! การเรียกคืนคำสั่งสุดท้ายหรือไม่
rubo77

เป็น-aความจำเป็นจริงๆ? >จะเขียนทับไฟล์tee -aจะต่อท้ายซึ่งจะเป็น>>
rubo77

3

ดูเหมือนจะง่ายเหมือนsudo sh -c "!!":

$ cd /
$ echo hello > foo
bash: foo: Permission denied
$ sudo sh -c "!!"
sudo sh -c "echo hello > foo"
$ ls -l foo
-rw-r--r-- 1 root root 6 Jun 20 16:21 foo

3
หากคำสั่งใช้เครื่องหมายคำพูดนี่ไม่จำเป็นต้องเทียบเท่ากัน พิจารณาecho "foo bar"ซึ่งจะกลายเป็นsh -c "echo "foo bar""ที่เพิ่งจะพิมพ์แทนfoo foo bar
godlygeek

ฉันลองsudo sh -c '!!'แทนคำสั่งของคุณ แต่ไม่ได้ผลเช่นกัน
rubo77

ถ้าคำสั่งของคุณใช้คำพูดเดี่ยวและคู่? หรือเครื่องหมายคำพูดคู่และการขยายตัวแปร? หากผู้ใช้ไม่ได้: a=bแล้วecho "$a" >fileและจากนั้นsudo sh -c '!!'ก็จะขยายตัวออกไปsudo sh -c 'echo $a >file'ซึ่งจะพิมพ์บรรทัดว่างแทนการเข้าb file
godlygeek

ดังนั้นอาจจะมีทางออกที่ดียิ่งขึ้นอย่างใด?
rubo77

1
ฉันไม่คิดว่าจะมีวิธีแก้ปัญหาใด ๆ ที่จะทำงานได้ 100% โดยที่คุณไม่จำเป็นต้องแก้ไขคำสั่ง การใช้sudoเพื่อรับรูทเชลล์แล้วคัดลอกและวางคำสั่งลงในนั้นจะใกล้เคียงที่สุด แต่จะล้มเหลวหากคำสั่งนั้นคาดว่าจะใช้ตัวแปรที่ตั้งค่าไว้ในเชลล์ที่ไม่ใช่รูทของคุณ ใช้sudo sh -c "!!"งานได้ดีสำหรับคำสั่งง่าย ๆ แต่เต็มไปด้วยคำสั่งที่ซับซ้อน ฉันคิดว่าคำแนะนำที่ดีที่สุดคืออย่าคาดหวังว่าจะมีคำสั่งบางอย่างที่ใช้งานได้ 100% - เรียนรู้วิธีแก้ปัญหาที่เป็นไปได้และนำไปใช้ในแนวทางที่เหมาะสม
godlygeek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.