Тимчасово збільшується час очікування 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

Як це не має 1000+ оновлень ??? Коротка версія є приголомшливою. (Але я думаю, що кращий приклад міг би допомогти.)
MountainX для Моніки Стейліо

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 &

Я думаю, що версія gist була б кращою, тому що якщо вона sudo -Kбуде викликана в іншому місці скрипту оболонки, ваша версія буде кричати sudo: a password is requiredна stderr щохвилини.
Rockallite

@Rockallite Ви маєте на увазі мою пов'язану суть? Вони насправді однакові.
Бор

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 хвилин, і у мене є окремі команди встановити команди, які проходять далеко поза цим.
Арелій

Хм. Добре. Не можна багато чого робити окрім збільшення часу очікування. Неможливо тимчасово встановити це.
coredump

0

База на суті, яку надав Грегорі Перкінс, і мій досвід, ось мій однорядний:

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Перенаправити потік помилок в whileциклі до порожнечі, так що повідомлення про помилки , що генеруються з допомогою будь-яких команд всередині циклу буде відкинуто.

    • -nВаріант sudoзапобігає його запитуючи користувача для пароля, але вивести повідомлення про помилку і вихід , якщо необхідно отримати пароль.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.