Tạm thời tăng thời gian chờ của sudo trong suốt thời gian của tập lệnh cài đặt


22

Tôi đang cố gắng viết một tập lệnh sẽ cài đặt một loạt phần mềm và tôi không muốn phải chạy mọi thứ như rootvậy, vì vậy tôi muốn có thể nhắc nhập mật khẩu và sau đó tiến hành cài đặt, sử dụng sudohoặc suđể có được đặc quyền khi tôi cần chúng.

Tôi đã làm một sudo -vdấu nhắc nhập mật khẩu ở đầu tập lệnh, và sau đó chỉ sử dụng sudo bình thường sau đó. Điều này hoạt động rất tốt cho đến khi tôi nhận được một cài đặt duy nhất mất thời gian chờ.

Tôi không muốn phải tăng thời gian chờ vĩnh viễn. Có cách nào để tôi có thể tăng thời gian chờ của sudo cho phiên hiện tại không?

Câu trả lời:


8

Bạn có thể thiết lập một vòng lặp chạy trong nền để định kỳ thực hiện "sudo -v", mẹo tất nhiên là làm cho vòng lặp kết thúc một cách sạch sẽ khi tập lệnh của bạn kết thúc. Vì vậy, phải có một số loại giao tiếp giữa hai quá trình; Các tập tin tmp là tốt cho điều này, và chúng cũng có thể dễ dàng được dọn sạch sau khi tập lệnh chạy. (Một kịch bản cài đặt thường làm điều này, dù sao đi nữa.)

Ví dụ: (loại bỏ các câu lệnh 'echo' để sử dụng điều này; chúng chỉ hiển thị "đang hoạt động"):

#!/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

Sau đó, bạn sẽ thấy ... (lưu ý: pid được đưa vào tệp tmp, để bạn có thể dễ dàng giết nó. Tuy nhiên, điều đó không cần thiết):

$ ./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

Tôi thích câu trả lời của michael_n, nhưng có mong muốn phi lý nhất là không sử dụng tệp tạm thời. Có lẽ điều này có thể cung cấp một số quan điểm.

Giải pháp của tôi là:

#!/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!"

Một lần nữa, echochúng không liên quan ...

$ ./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

Một lần nữa, ctrl-c cũng hoạt động ...

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

6
Và một giải pháp ngắn gọn hơn: gist.github.com/3118588
Gregory Perkins

Làm thế nào mà cái này không có hơn 1000 upvote ??? Phiên bản cô đọng thật tuyệt vời. (Nhưng một ví dụ tốt hơn sẽ giúp ích, tôi nghĩ vậy.)
MountainX cho Monica Cellio

3

Dựa trên ý chính này , tôi đã tạo ra một phiên bản ngắn gọn và rõ ràng:

# 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 &

Tôi nghĩ rằng phiên bản chính sẽ tốt hơn, bởi vì nếu sudo -Kđược gọi ở vị trí khác của tập lệnh shell, phiên bản của bạn sẽ hét lên sudo: a password is requiredstderr mỗi phút.
Rockallite

@Rockallite Ý bạn là ý chính của tôi? Họ thực sự giống nhau.
Bohr

0

Theo sudotrang nam:

   -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.

Vì vậy, tôi đoán rằng nếu bạn thêm một số sudo -vđiểm trong tập lệnh thiết lập của mình để xác thực phiên (và không chỉ ở đầu), bạn sẽ nhận được những gì bạn muốn, vì mỗi lần nó sẽ tăng thời gian chờ (nó chỉ hỏi lại mật khẩu nếu thời gian chờ đạt được). Vấn đề duy nhất sẽ là nếu có một lệnh trên tập lệnh của bạn mất nhiều thời gian hơn thời gian chờ (vì vậy ngay cả khi bạn xác thực ngay sau khi hết thời gian, nó sẽ hết hạn trước khi hoàn thành xác nhận khác), nhưng đây là trường hợp rất cụ thể.

Điều gì xảy ra là chỉ sử dụng sudokhông làm tăng thời gian chờ và sudo -vkhông thực thi lệnh, vì vậy bạn phải sử dụng sudo -vnhiều lần hơn để xác thực phiên.


Vâng, cảm ơn. Vấn đề là thời gian chờ sudo của tôi gần hơn 5 phút và tôi có các lệnh cài đặt đơn lẻ vượt quá thời gian đó.
Arelius

Hừm. Tốt. Không có nhiều việc phải làm ngoài việc tăng thời gian chờ. Không có cách nào để đặt nó tạm thời.
coredump

0

Dựa trên ý chính được cung cấp bởi Gregory Perkins và kinh nghiệm của tôi, đây là tài liệu chính của tôi:

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

Hoặc là

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

Giải thích

  • trap "exit" INT TERM; trap "kill 0" EXIT: Điều này sẽ đưa xuống toàn bộ cây quy trình khi thoát hoặc SIGINT / SIGTERM.

  • sudo -v || exit $?: Yêu cầu nhập mật khẩu trước và lưu thông tin xác thực bảo mật, nhưng không chạy lệnh. Nếu mật khẩu không đúng, hãy thoát với mã được trả về bởi sudo.

  • sleep 1: Trì hoãn một chút để thông tin bảo mật được lưu một cách hiệu quả. Nếu sudo tiếp theo chạy quá sớm, nó sẽ không biết vì thông tin đăng nhập chưa được lưu, do đó sẽ yêu cầu nhập lại mật khẩu.

  • while true; do sleep 60; sudo -nv; done 2>/dev/null &: Cập nhật thông tin bảo mật sudo hiện có nhiều lần. Lưu ý rằng phiên bản này khác với một trong những ý chính được liên kết: nó chạy sleep 60trước, và sau đó sudo -nv.

    • Các &nhà điều hành đặt toàn bộ whilevòng lặp vào nền, chạy nó như một quá trình con.

    • Các 2>/dev/nullchuyển hướng stderr của whilevòng lặp để khoảng trống, vì vậy thông báo lỗi được tạo ra bởi bất kỳ lệnh bên trong vòng lặp sẽ bị loại bỏ.

    • Các -ntùy chọn sudongăn chặn nó từ khiến người dùng cho một mật khẩu, nhưng hiển thị một thông báo lỗi và thoát nếu mật khẩu là bắt buộc.

    • Không có kill -0 "$$" || exitnhư trong ý chính được liên kết, bởi vì hai traps đầu tiên sẽ thực hiện công việc. Nó sẽ không phải ngủ trong 59 giây trước khi phát hiện ra quá trình cha mẹ không chạy!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.