Назад | Перейти на главную страницу

Временное увеличение таймаута sudo на время установки скрипта

Я пытаюсь написать сценарий, который установит кучу программного обеспечения, и мне бы не хотелось запускать все как root, поэтому я хотел бы иметь возможность запрашивать пароль, а затем приступать к установке, используя sudo или su чтобы получить привилегии, когда они мне нужны.

Я делал sudo -v для запроса пароля в начале сценария, а затем просто с помощью sudo в дальнейшем. Это отлично работает, пока я не доберусь до единственной установки, которая берет на себя время ожидания.

Я бы предпочел не увеличивать время ожидания навсегда. Есть ли способ увеличить тайм-аут sudo только для текущего сеанса?

Мне понравился ответ 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

Вы можете настроить цикл, который запускается в фоновом режиме, для периодического выполнения "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)

Основываясь на этом суть, Я сделал лаконичную и чистую версию:

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

Основываясь на суть предоставленный Грегори Перкинс и мой опыт, вот мой однострочный:

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 60 сначала, а потом sudo -nv.

    • В & оператор ставит весь while цикл в фоновом режиме, выполняя его как дочерний процесс.

    • В 2>/dev/null перенаправить stderr из while цикл к пустоте, поэтому сообщения об ошибках, созданные любыми командами внутри цикла, будут отброшены.

    • В -n вариант sudo предотвращает запрос пароля у пользователя, но отображает сообщение об ошибке и завершает работу, если пароль требуется.

    • Нет никаких kill -0 "$$" || exit как в связанной сущности, потому что первые два traps сделает свою работу. Ему не придется спать в течение 59 секунд, прежде чем он обнаружит, что родительский процесс не запущен!

Согласно 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 еще раз для подтверждения сеанса.