Augmentation temporaire du délai d'expiration de sudo pendant la durée d'un script d'installation

22

J'essaie d'écrire un script qui installera un tas de logiciels et j'aimerais ne pas avoir à tout exécuter comme rootça, donc j'aimerais pouvoir demander un mot de passe et ensuite procéder à l'installation, en utilisant sudoou supour obtenir des privilèges quand j'en ai besoin.

Je faisais un sudo -vpour demander un mot de passe au début du script, puis j'utilisais sudo normalement plus tard. Cela fonctionne très bien jusqu'à ce que j'arrive à une seule installation qui prend le relais.

Je préfère ne pas avoir à augmenter définitivement le délai d'attente. Existe-t-il un moyen d'augmenter uniquement le délai d'expiration de sudo pour la session en cours?

Arelius
la source

Réponses:

8

Vous pouvez configurer une boucle qui s'exécute en arrière-plan pour exécuter périodiquement "sudo -v", l'astuce consiste bien sûr à ce que la boucle se termine proprement lorsque votre script se termine. Il doit donc y avoir un certain type de communication entre les deux processus; Les fichiers tmp sont parfaits pour cela, et ils peuvent également être facilement nettoyés après l'exécution du script. (Un script d'installation fait généralement cela, de toute façon.)

Par exemple (supprimez les instructions 'echo' pour utiliser ceci; celles-ci montrent simplement que cela "fonctionne"):

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

Ensuite, vous verrez ... (note: le pid est placé dans le fichier tmp, juste pour que vous puissiez facilement le tuer. Ce n'est pas nécessaire, cependant):

$ ./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)
Michael
la source
9

J'ai aimé la réponse de michael_n, mais j'avais le désir le plus irrationnel de ne pas utiliser de fichier temporaire. Peut-être que cela peut fournir une certaine perspective.

Ma solution était:

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

Encore une fois, les echo's sont étrangers ...

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

Encore une fois, ctrl-c fonctionne aussi ...

$ ./sudoping.sh 
Starting background sudo ping...
ok  
Sudo ping!
Sudo pinging in PID = 47599
Sudo ping!
^CStopping sudo ping in PID = 47599
Gregory Perkins
la source
6
Et une solution plus succincte: gist.github.com/3118588
Gregory Perkins
Comment cela n'a-t-il pas plus de 1000 votes positifs ??? La version succincte est impressionnante. (Mais un meilleur exemple aiderait, je pense.)
MountainX pour Monica Cellio
3

Sur la base de cet essentiel , j'ai fait une version concise et propre:

# 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 &
Bohr
la source
Je pense que la version gist serait meilleure, car si elle sudo -Kest invoquée à un autre endroit du script shell, votre version crierait sudo: a password is requiredau stderr chaque minute.
Rockallite
@ Rockockite Voulez-vous dire mon essentiel lié? Ce sont en fait les mêmes.
Bohr
0

Selon la sudopage de manuel:

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

Donc, je suppose que si vous en ajoutez sudo -ven plus de points de votre script de configuration pour valider la session (et pas seulement au début), vous obtiendrez ce que vous voulez, car à chaque fois cela augmentera le délai (il ne demandera à nouveau le mot de passe que si le délai est atteint). Le seul problème sera s'il y a une commande sur votre script qui prend plus de temps que le délai d'expiration (donc même si vous validez juste après, le délai expirera avant de se terminer pour une autre validation), mais c'est un cas très spécifique.

Ce qui se passe, c'est que l'utilisation sudon'augmente pas le délai d'expiration et sudo -vn'exécute pas de commande, vous devez donc utiliser sudo -vplus de temps pour valider la session.

coredump
la source
Oui merci. Le problème est que mon délai d'attente sudo est plus proche de 5 minutes, et j'ai des commandes make install uniques qui vont bien au-delà.
Arelius
Hmm. Bien. Il n'y a pas grand-chose à faire à part augmenter le délai d'attente alors. Il n'y a aucun moyen de le régler temporairement.
coredump
0

Sur la base de l' essentiel fourni par Gregory Perkins et de mon expérience, voici mon one-liner:

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

Ou

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

Explications

  • trap "exit" INT TERM; trap "kill 0" EXIT: Cela supprimera tout l'arborescence de processus à la sortie ou SIGINT / SIGTERM.

  • sudo -v || exit $?: Demandez le mot de passe à l'avance et mettez en cache les informations d'identification de sécurité, mais n'exécutez pas de commande. Si le mot de passe n'est pas correct, quittez avec le code renvoyé par sudo.

  • sleep 1: Retardez un peu pour que les informations de sécurité soient effectivement enregistrées. Si le prochain sudo s'exécute trop tôt, il ne le saura pas car les informations d'identification ne sont pas encore enregistrées, il vous demandera donc à nouveau le mot de passe.

  • while true; do sleep 60; sudo -nv; done 2>/dev/null &: Mettez à jour les informations d'identification de sécurité sudo à plusieurs reprises. Notez que cette version diffère de celle de l'essentiel lié: elle s'exécute en sleep 60premier, puis sudo -nv.

    • L' &opérateur place la whileboucle entière en arrière-plan, l'exécutant en tant que processus enfant.

    • La 2>/dev/nullredirection du stderr de la whileboucle vers le vide, donc les messages d'erreur générés par toutes les commandes à l'intérieur de la boucle seront ignorés.

    • L' -noption de l' sudoempêche d'inviter l'utilisateur à saisir un mot de passe, mais affiche un message d'erreur et quitte si un mot de passe est requis.

    • Il n'y a rien kill -0 "$$" || exitcomme dans l'essentiel lié, parce que les deux premiers traps feront l'affaire. Il n'aura pas à dormir pendant 59 secondes avant de comprendre que le processus parent n'est pas en cours d'exécution!

Rockallite
la source