เพิ่มการหมดเวลาของ sudo ชั่วคราวในช่วงเวลาของสคริปต์การติดตั้ง


22

ฉันกำลังพยายามเขียนสคริปต์ที่จะติดตั้งซอฟต์แวร์จำนวนมากและฉันไม่ต้องการเรียกใช้ทุกอย่างrootดังนั้นฉันจึงอยากจะขอรหัสผ่านจากนั้นไปที่การติดตั้งโดยใช้sudoหรือsuเพื่อรับสิทธิพิเศษเมื่อต้องการ

ฉันกำลังทำsudo -vเพื่อขอรหัสผ่านที่จุดเริ่มต้นของสคริปต์และจากนั้นเพียงใช้ sudo ตามปกติในภายหลัง มันใช้งานได้ดีจนกระทั่งฉันได้ติดตั้งครั้งเดียวซึ่งหมดเวลา

ฉันไม่ต้องการเพิ่มการหมดเวลาอย่างถาวร มีวิธีที่ฉันสามารถเพิ่มการหมดเวลาของ sudo สำหรับเซสชันปัจจุบันเท่านั้นหรือไม่

คำตอบ:


8

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

ตัวอย่างเช่น (ลบคำสั่ง 'echo' เพื่อใช้สิ่งนี้เพียงแสดงว่า "ทำงาน"):

#!/bin/bash
log=running_setup.txt
sudo_stat=sudo_status.txt

echo "========= running script $$ ========"
echo $$ >> $sudo_stat
trap 'rm -f $sudo_stat >/dev/null 2>&1' 0
trap "exit 2" 1 2 3 15

sudo_me() {
 while [ -f $sudo_stat ]; do
  echo "checking $$ ...$(date)"
  sudo -v
  sleep 5
 done &
}


echo "=setting up sudo heartbeat="
sudo -v
sudo_me

echo "=running setup=" | tee $log
while [ -f $log ]
do
 echo "running setup $$ ...$(date) ===" | tee -a $log
 sleep 2
done

# finish sudo loop
rm $sudo_stat

จากนั้นคุณจะเห็น ... (หมายเหตุ: pid จะถูกใส่ลงในไฟล์ tmp เพื่อให้คุณสามารถฆ่ามันได้อย่างง่ายดายโดยไม่จำเป็น แต่อย่างใด):

$ ./do_it.sh
========= running script 6776 ========
=setting up sudo heartbeat=
[sudo] password for user: 
=running setup=
checking 6776 ...Wed May  4 16:31:47 PDT 2011
running setup 6776 ...Wed May  4 16:31:48 PDT 2011 ===
running setup 6776 ...Wed May  4 16:31:50 PDT 2011 ===
running setup 6776 ...Wed May  4 16:31:52 PDT 2011 ===
checking 6776 ...Wed May  4 16:31:53 PDT 2011
running setup 6776 ...Wed May  4 16:31:54 PDT 2011 ===
<ctrl-c>  (cleans up files, then exits)

9

ฉันชอบคำตอบของ michael_n แต่มีความปรารถนาที่ไม่มีเหตุผลที่สุดที่จะไม่ใช้ไฟล์ชั่วคราว บางทีนี่อาจให้มุมมองบางอย่าง

ทางออกของฉันคือ:

#!/bin/bash
function sudo_ping() {
    if [[ ! -z $SUDO_PID ]]; then
        if [[ $1 -eq stop ]]; then
            echo "Stopping sudo ping in PID = $SUDO_PID"
            kill $SUDO_PID
            return
        else
            echo "Already sudo pinging in PID = $SUDO_PID"
            return
        fi
    fi

    echo "Starting background sudo ping..."
    sudo -v
    if [[ $? -eq 1 ]]; then
        echo "Oops, wrong password."
        return
    fi
    sudo echo "ok"

    while true; do
        echo 'Sudo ping!'
        sudo -v
        sleep 1
    done &
    SUDO_PID=$!
    sudo echo "Sudo pinging in PID = $SUDO_PID"

    # Make sure we don't orphan our pinger
    trap "sudo_ping stop" 0
    trap "exit 2" 1 2 3 15
}

sudo_ping
sleep 5
echo "Goodbye!"

อีกครั้งสิ่งechoที่อยู่ภายนอก ...

$ ./sudoping.sh 
Starting background sudo ping...
Password:
ok  
Sudo ping!
Sudo pinging in PID = 47531
Sudo ping!
Sudo ping!
Sudo ping!
Sudo ping!
Goodbye!
Stopping sudo ping in PID = 47531

อีกครั้ง ctrl-c ก็ทำงานเช่นกัน ...

$ ./sudoping.sh 
Starting background sudo ping...
ok  
Sudo ping!
Sudo pinging in PID = 47599
Sudo ping!
^CStopping sudo ping in PID = 47599

6
และวิธีแก้ปัญหาที่กระชับยิ่งขึ้น: gist.github.com/3118588
Gregory Perkins

สิ่งนี้ไม่มี upvotes 1,000+ อย่างไร เวอร์ชั่นย่อนั้นยอดเยี่ยมมาก (แต่เป็นตัวอย่างที่ดีกว่านี้จะช่วยได้ฉันคิดว่า)
MountainX สำหรับ Monica Cellio

3

ตามส่วนสำคัญนี้ฉันได้ทำรุ่นที่รัดกุมและสะอาด:

# Prevent sudo timeout
sudo -v # ask for sudo password up-front
while true; do
  # Update user's timestamp without running a command
  sudo -nv; sleep 1m
  # Exit when the parent process is not running any more. In fact this loop
  # would be killed anyway after being an orphan(when the parent process
  # exits). But this ensures that and probably exit sooner.
  kill -0 $$ 2>/dev/null || exit
done &

ฉันคิดว่าเวอร์ชั่นสำคัญจะดีกว่าเพราะถ้าsudo -Kมีการเรียกใช้ในที่อื่น ๆ ของเชลล์สคริปต์เวอร์ชันของคุณจะตะโกนใส่sudo: a password is requiredstderr ทุกนาที
Rockallite

@Rockallite คุณหมายถึง gist ที่เชื่อมโยงของฉัน? พวกเขาเหมือนกันจริง ๆ
Bohr

0

ตามsudoหน้าคน:

   -v          If given the -v (validate) option, sudo will update the user's time stamp,
               prompting for the user's password if necessary.  This extends the sudo timeout for
               another 15 minutes (or whatever the timeout is set to in sudoers) but does not run
               a command.

ดังนั้นฉันเดาว่าถ้าคุณเพิ่มบางsudo -vจุดของสคริปต์การตั้งค่าของคุณเพื่อตรวจสอบเซสชั่น (และไม่เพียง แต่ตอนเริ่มต้น) คุณจะได้รับสิ่งที่คุณต้องการเพราะแต่ละครั้งมันจะเพิ่มการหมดเวลา (ถามเฉพาะรหัสผ่านอีกครั้งว่า หมดเวลาถึง) ปัญหาเดียวคือถ้ามีคำสั่งในสคริปต์ของคุณที่ใช้เวลามากกว่าการหมดเวลา (ดังนั้นแม้ว่าคุณจะตรวจสอบหลังจากหมดเวลาการหมดเวลาจะหมดอายุก่อนที่จะทำการตรวจสอบอื่น) แต่นี่เป็นกรณีที่เฉพาะเจาะจงมาก

สิ่งที่เกิดขึ้นคือการใช้เพียงอย่างเดียวsudoจะไม่เพิ่มการหมดเวลาและsudo -vไม่ได้ดำเนินการคำสั่งดังนั้นคุณต้องใช้sudo -vเวลามากขึ้นในการตรวจสอบเซสชัน


ใช่ขอบคุณ. ปัญหาคือหมดเวลา sudo ของฉันใกล้ถึง 5 นาทีและฉันมีคำสั่งติดตั้งแบบเดี่ยวที่ผ่านมานานแล้ว
Arelius

อืมมม ดี. มีไม่มากที่จะทำนอกเหนือจากการเพิ่มการหมดเวลาแล้ว ไม่มีวิธีตั้งค่าชั่วคราว
coredump

0

โดยสรุปสาระสำคัญจากGregory Perkinsและประสบการณ์ของฉันนี่เป็นหนึ่งในสายการบินของฉัน:

trap "exit" INT TERM; trap "kill 0" EXIT; sudo -v || exit $?; sleep 1; while true; do sleep 60; sudo -nv; done 2>/dev/null &

หรือ

trap "exit" INT TERM
trap "kill 0" EXIT
sudo -v || exit $?
sleep 1
while true; do
    sleep 60
    sudo -nv
done 2>/dev/null &

คำอธิบาย

  • trap "exit" INT TERM; trap "kill 0" EXIT: นี่จะเป็นการทรีกระบวนการทั้งหมดเมื่อออกหรือ SIGINT / SIGTERM

  • sudo -v || exit $?: ขอรหัสผ่านล่วงหน้าและแคชข้อมูลรับรองความปลอดภัย แต่อย่าเรียกใช้คำสั่ง หากรหัสผ่านไม่ถูกต้องให้ออกพร้อมรหัสที่ส่งคืนโดย sudo

  • sleep 1: ล่าช้านิดหน่อยเพื่อให้ข้อมูลรับรองความปลอดภัยได้รับการบันทึกอย่างมีประสิทธิภาพ หาก sudo ถัดไปทำงานเร็วเกินไปมันจะไม่รู้เพราะข้อมูลประจำตัวยังไม่ได้บันทึกดังนั้นจะขอรหัสผ่านอีกครั้ง

  • while true; do sleep 60; sudo -nv; done 2>/dev/null &: อัปเดตข้อมูลประจำตัวด้านความปลอดภัยของ sudo ซ้ำ ๆ แจ้งให้ทราบว่ารุ่นนี้แตกต่างจากหนึ่งในส่วนสำคัญที่เชื่อมโยง: มันจะทำงานก่อนแล้วsleep 60sudo -nv

    • &ประกอบการทำให้ทั้งwhileห่วงเป็นพื้นหลังที่ใช้เป็นกระบวนการเด็ก

    • การ2>/dev/nullเปลี่ยนเส้นทาง stderr ของwhileลูปไปเป็นโมฆะดังนั้นข้อความแสดงข้อผิดพลาดที่สร้างขึ้นโดยคำสั่งใด ๆ ภายในลูปจะถูกยกเลิก

    • -nตัวเลือกในการsudoป้องกันไม่ให้มันแจ้งให้ผู้ใช้รหัสผ่าน แต่แสดงข้อผิดพลาดและออกถ้าต้องมีรหัสผ่าน

    • ไม่มีkill -0 "$$" || exitส่วนสำคัญในการเชื่อมโยงเพราะสองคนแรกtrapจะทำงาน มันจะไม่ต้องนอนเป็นเวลา 59 วินาทีก่อนที่มันจะบอกว่ากระบวนการผู้ปกครองไม่ได้ทำงาน!

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