sudo ในสคริปต์ที่ไม่โต้ตอบ


9

A && B && Cฉันมีสคริปต์ที่รันสามฟังก์ชั่น:

ฟังก์ชั่นBจะต้องทำงานเป็นผู้ใช้ขั้นสูงในขณะที่AและCไม่

ฉันมีวิธีแก้ปัญหาต่าง ๆ แต่สิ่งเหล่านี้ไม่เป็นที่พอใจ

  1. sudo สคริปต์ทั้งหมด: sudo 'A && B && C'

    ดูเหมือนว่าเป็นความคิดที่ไม่ถูกต้องในการใช้งานAและCในฐานะผู้ใช้ระดับสูงหากไม่จำเป็น

  2. ทำให้สคริปต์โต้ตอบ: A && sudo B && C

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

  3. วิธีการแก้ปัญหาโง่: sudo : && A && sudo -n B && C

    ครั้งแรกมันดูเหมือนว่าโง่ที่จะใช้ไม่มี-op แรกและเราก็ต้องข้ามนิ้วมือของฉันที่ไม่ได้ไปใช้เวลามากกว่าsudo$sudo_timeout

  4. วิธีแก้ปัญหาสมมุติฐาน (ฉันหวังว่าคุณจะบอกฉันมันมีอยู่):

    sudo --store-cred 'A && sudo --use-cred-from-parent-sudo B && C'

    นั่นจะทำให้รหัสผ่านของฉันเริ่มต้นจากนั้นใช้ข้อมูลประจำตัวนั้นเมื่อจำเป็นเท่านั้น

คุณมีความคิดเห็นอย่างไรกับเรื่องนี้? ฉันประหลาดใจมากที่ไม่มีวิธีแก้ปัญหาดังกล่าวเพราะฉันคิดว่ามันเป็นปัญหาที่พบได้บ่อยมาก (เกี่ยวกับmake all && sudo make install)


3
คุณสามารถทำให้สคริปต์ที่คุณดำเนินการกับ sudo แต่ในสคริปต์รันAและชิ้นส่วนอย่างชัดเจนโดยใช้C su -l some_non_priviliged_userไม่มีปัญหาการหมดเวลาและไม่มี Priveliges สำหรับ A และ C ฉันไม่คิดว่า 4 เป็นไปได้sudoดูเหมือนว่า "สถานะทั่วโลก" สำหรับผู้ใช้
Anthon

คำตอบ:


7

ฉันคิดว่าสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือเปิดสคริปต์ด้วยsudoแล้วเปิดกระบวนการที่คุณต้องการเรียกใช้ในฐานะผู้ใช้ปกติอย่างชัดเจนด้วยsu userหรือsudo -u user:

#!/usr/bin/env bash

## Detect the user who launched the script
usr=$(env | grep SUDO_USER | cut -d= -f 2)

## Exit if the script was not launched by root or through sudo
if [ -z $usr ] && [ $USER = "root" ]
then
    echo "The script needs to run as root" && exit 1
fi

## Run the job(s) that don't need root
sudo -u $usr commandA

## Run the job that needs to be run as root
commandB

9

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

บรรทัดตัวอย่างสำหรับสคริปต์ที่เรียกว่า/usr/local/bin/bossyอาจมีลักษณะเช่นนี้

ALL ALL = (root) NOPASSWD: /usr/local/bin/bossy

และคุณจะใช้สิ่งนี้

A && sudo bossy && C

สำหรับตัวอย่างนี้ผมถือว่ารวมถึงPATH /usr/local/binถ้าไม่เช่นนั้นให้ใช้เส้นทางแบบเต็มไปยังสคริปต์เช่นsudo /usr/local/bin/bossy


โหวตขึ้นสำหรับแนวทางที่ปลอดภัยที่สุด
eyoung100

0

คุณอาจต้องการใช้!requirettyตัวเลือกในsudoเช่นเดียวกับNOPASSWDตัวเลือก แต่โปรดจำไว้ว่านี่จะช่วยลดความปลอดภัย


1
เนื่องจากปัญหาถูกกำหนดว่าไม่ต้องการให้สคริปต์เป็นแบบโต้ตอบ # 2 พร้อม/etc/sudoersรายการสำหรับผู้ใช้ในการดำเนินการคำสั่งBด้วยNOPASSWDเป็นคำตอบที่ถูกต้อง
Andrew

นั่นคือ "คุณสามารถทำ X หรือ Y" มันคือ "คุณสามารถทำ X และ Y" ทั้งคู่เท่านั้นที่จะแก้ปัญหาได้ บางทีฉันควรพูดคำตอบของฉันอีกครั้ง
Steve Wills

0

สร้างคำตอบของฉันเพื่ออนุมัติอนุญาต sudo ล่วงหน้าหรือไม่ (ดังนั้นจึงสามารถเรียกใช้ในภายหลัง)เขียนสคริปต์สอง:

  • ABC_script:

    #!/bin/sh
    sudo -b ./B_script
    A  &&  > A_is_done
    while [ ! -f B_is_done ]
    do
            sleep 60
    done
    rm -f B_is_done
    C
  • B_script:

    #!/bin/sh
    while [ ! -f A_is_done ]
    do
            sleep 60
    done
    rm -f A_is_done
    B  &&  > B_is_done

วิ่ง./ABC_script:

  • sudo -b ./B_scriptมันจะทำงาน สิ่งนี้จะถามรหัสผ่าน ( ทันทีหลังจากที่คุณเรียกใช้ABC_script) สมมติว่าป้อนรหัสผ่านที่ถูกต้องมันจะวางไข่B_scriptในb ackground (เพราะ-bถูกระบุ) เป็นรูท sudo sh -c "./B_script &"นี้น่าจะเทียบเท่ากับ
  • B_scriptABC_scriptเริ่มทำงานแบบไม่พร้อมกันในแบบคู่ขนานกับ  B_scriptทดสอบการมีอยู่ของไฟล์ที่เรียกA_is_done และวนซ้ำจนกว่าจะปรากฏขึ้น
  • ในแบบคู่ขนานวิ่งABC_script Aถ้า / เมื่อเสร็จสิ้นการประสบความสำเร็จในสคริปต์สร้างไฟล์ที่เรียกว่าAA_is_done
  • ABC_scriptจากนั้นทดสอบการมีอยู่ของไฟล์ที่เรียกB_is_done และวนซ้ำจนกว่าจะปรากฏขึ้น
  • ในแบบคู่ขนาน B_scriptตรวจจับการมีอยู่ของA_is_doneและแยกออกจากลูป มันลบไฟล์และทำงานA_is_done Bโปรดจำไว้ว่าB_scriptกำลังรันเป็นรูทดังนั้นจึงรันBเป็นรูท หาก / เมื่อBเสร็จเรียบร้อยสคริปต์จะสร้างไฟล์ชื่อB_is_doneและออก
  • ในแบบคู่ขนาน ABC_scriptตรวจจับการมีอยู่ของB_is_doneและแยกออกจากลูป มันจะลบB_is_doneไฟล์ จำไว้ว่าให้B_scriptรันในฐานะรูทดังนั้นB_is_doneเจ้าของจะเป็นเจ้าของรูทและคุณต้องการใช้rm -fเพื่อหลีกเลี่ยงการขอการยืนยัน ABC_scriptจากนั้นเรียกใช้Cและออกจาก

หมายเหตุสำหรับการปรับแต่งเพิ่มเติม:

  • ABC_scriptอาจจะทำงานโดยเส้นทางที่แน่นอนมากกว่าB_script./
  • แทนที่จะA_is_doneและB_is_done, ABC_scriptอาจจะสร้างแบบสุ่มชื่อไฟล์ที่ไม่ซ้ำกัน
  • จำเป็นต้องมีการเตรียมการสำหรับสคริปต์ที่รอการสปินรอรับการแจ้งเตือนหากโปรแกรมที่กำลังรอนั้นสิ้นสุดลง แต่ล้มเหลว (ตอนนี้ถ้าAล้มเหลวสคริปต์ทั้งสองจะเข้าสู่การวนรอบรอไม่สิ้นสุด) สิ่งนี้อาจง่ายเหมือนการเปลี่ยนแปลง

    A  &&  > A_is_done

    ถึง

    A; echo $? > A_is_done

    จากนั้นทำการปรับแก้สปินรอเพื่ออ่านX_is_doneไฟล์และดำเนินการต่อถ้ามันมี 0 และออกเป็นอย่างอื่น


-3

เป็นคนโง่ ใช้หลายบรรทัด

if A; then

    if sudo B ; then
        C
    fi
fi

การแก้ปัญหาข้อกังวลของฉันเป็นอย่างไร ปัญหาไม่เกี่ยวกับ&&
Antoine Pelisse

&& หยุดการทำงานเมื่อคำสั่งแรกล้มเหลว คำสั่ง if ทำสิ่งนี้อย่างละเอียดมากขึ้น ประเด็นของฉันคือการทำให้งานของคุณเสร็จแม้ว่าจะไม่สวย
Robert Jacobs

1
นี้เป็นอะไรมากไปกว่าขึ้น verbose รุ่นของตัวเลือกที่ A && sudo B && C2: เช่นเดียวกับแอนทอนอธิบายในคำถาม; สิ่งนี้จะไม่ถามรหัสผ่านจนกว่าจะAเสร็จสิ้นและเขาไม่ต้องการที่จะรอหรือให้สคริปต์รอเขา
สกอตต์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.