Aumentando temporariamente o tempo limite do sudo durante um script de instalação

22

Eu estou tentando escrever um script que irá instalar um monte de software e eu gostaria de não ter que executar tudo como root , então eu gostaria de poder pedir uma senha e então ir sobre a instalação, usando sudo ou su para obter privilégios quando eu precisar deles.

Eu estava fazendo um sudo -v para solicitar uma senha no início do script e depois usar o sudo normalmente mais tarde. Isso funciona muito bem até chegar a uma única instalação que assume o tempo limite.

Prefiro não ter que aumentar permanentemente o tempo limite. Existe uma maneira de aumentar o tempo limite do sudo apenas para a sessão atual?

    
por Arelius 04.05.2011 / 05:42

5 respostas

8

Você pode configurar um loop que é executado em segundo plano para executar periodicamente o "sudo -v", o truque, é claro, é fazer com que o loop seja encerrado corretamente quando o script terminar. Então tem que haver algum tipo de comunicação entre os dois processos; Os arquivos tmp são bons para isso, e eles podem ser facilmente limpos após a execução do script. (Um script de instalação geralmente faz isso, de qualquer maneira.)

Por exemplo (remova as instruções 'echo' para usar isto; estas apenas mostram "working"):

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

Então você verá ... (nota: o pid é colocado no arquivo tmp, só assim você pode matá-lo facilmente. Não é necessário, no entanto):

$ ./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)
    
por 05.05.2011 / 01:37
9

Eu gostei da resposta de michael_n, mas tinha o desejo mais irracional de não usar um arquivo temporário. Talvez isso possa fornecer alguma perspectiva.

Minha solução foi:

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

Mais uma vez, os echo são estranhos ...

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

Novamente, ctrl-c também funciona ...

$ ./sudoping.sh 
Starting background sudo ping...
ok  
Sudo ping!
Sudo pinging in PID = 47599
Sudo ping!
^CStopping sudo ping in PID = 47599
    
por 02.07.2012 / 14:13
3

Com base nesta essência , criei uma versão concisa e limpa:

# 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 &
    
por 27.06.2015 / 12:41
0

De acordo com a página sudo man:

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

Então, se você adicionar sudo -v em mais pontos do script de configuração para validar a sessão (e não apenas no começo), você obterá o que deseja, já que a cada vez aumentará o tempo limite somente pergunta a senha novamente se o tempo limite for atingido). O único problema será se houver um comando no seu script que demore mais tempo do que o tempo limite (por isso, mesmo se você validar logo após o tempo limite expirará antes de completar outra validação), mas este é um caso muito específico. p>

O que acontece é que usar sudo não aumenta o tempo limite, e sudo -v não executa um comando, então você tem que usar sudo -v mais vezes para validar a sessão.

    
por 04.05.2011 / 07:28
0

Base na essência fornecida por Gregory Perkins e minha experiência, aqui está meu 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 &

Explicações

  • trap "exit" INT TERM; trap "kill 0" EXIT : Isso derrubará toda a árvore de processos ao sair ou SIGINT / SIGTERM.

  • sudo -v || exit $? : Solicite a senha na frente e armazene em cache as credenciais de segurança, mas não execute um comando. Se a senha não estiver correta, saia com o código retornado pelo sudo.

  • sleep 1 : Atrase um pouco para que as credenciais de segurança sejam efetivamente salvas. Se o próximo sudo for executado muito cedo, ele não saberá porque as credenciais ainda não foram salvas, portanto, solicitará a senha novamente.

  • while true; do sleep 60; sudo -nv; done 2>/dev/null & : Atualize as credenciais de segurança sudo existentes repetidamente. Note que esta versão difere da do gist linkado: ela executa sleep 60 first e, em seguida, sudo -nv .

    • O operador & coloca todo o loop while em segundo plano, executando-o como um processo filho.

    • O 2>/dev/null redireciona o stderr do loop while para o void, então as mensagens de erro geradas por quaisquer comandos dentro do loop serão descartadas.

    • A opção -n de sudo impede que o usuário solicite uma senha, mas exibe uma mensagem de erro e sai se uma senha for exigida.

    • Não há kill -0 "$$" || exit como na essência vinculada, porque os dois primeiros trap s farão o trabalho. Ele não precisará dormir por 59 segundos antes de descobrir que o processo pai não está em execução!

por 21.02.2017 / 11:33