Vorübergehend das Timeout von sudo für die Dauer eines Installationsskripts erhöhen

22

Ich versuche, ein Skript zu schreiben, das eine Reihe von Software installiert, und ich möchte nicht alles als ausführen müssen. Daher rootmöchte ich in der Lage sein, ein Kennwort einzugeben und dann mit sudooder die Installation durchzuführen suPrivilegien zu bekommen, wenn ich sie brauche.

Ich habe sudo -vzu Beginn des Skripts eine Eingabeaufforderung zur Eingabe eines Kennworts ausgeführt und später normalerweise nur sudo verwendet. Dies funktioniert gut, bis ich zu einer einzelnen Installation komme, die das Timeout übernimmt.

Ich möchte das Timeout lieber nicht dauerhaft verlängern. Kann ich das Timeout von sudo nur für die aktuelle Sitzung verlängern?

Arelius
quelle

Antworten:

8

Sie können eine Schleife einrichten, die im Hintergrund ausgeführt wird, um "sudo -v" regelmäßig auszuführen. Der Trick besteht natürlich darin, die Schleife beim Beenden des Skripts sauber zu beenden. Es muss also eine Art Kommunikation zwischen den beiden Prozessen geben. tmp-Dateien sind hierfür in Ordnung und können auch nach Ausführung des Skripts problemlos bereinigt werden. (Ein Installationsskript erledigt dies normalerweise sowieso.)

Zum Beispiel (entfernen Sie die 'echo'-Anweisungen, um dies zu verwenden; diese zeigen nur, dass es "funktioniert"):

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

Dann werden Sie sehen ... (Hinweis: Die PID wird in die tmp-Datei eingefügt, damit Sie sie leicht töten können. Dies ist jedoch nicht erforderlich.):

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

Ich mochte die Antwort von michael_n, hatte aber den irrationalsten Wunsch, keine temporäre Datei zu verwenden. Vielleicht kann dies eine Perspektive bieten.

Meine Lösung war:

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

Auch hier echosind die fremd ...

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

Wieder funktioniert Strg-C auch ...

$ ./sudoping.sh 
Starting background sudo ping...
ok  
Sudo ping!
Sudo pinging in PID = 47599
Sudo ping!
^CStopping sudo ping in PID = 47599
Gregory Perkins
quelle
6
Und eine prägnantere Lösung: gist.github.com/3118588
Gregory Perkins
Wie hat das nicht 1000+ Upvotes ??? Die prägnante Version ist fantastisch. (Aber ein besseres Beispiel würde helfen, denke ich.)
MountainX für Monica Cellio
3

Ausgehend von diesem Kern habe ich eine kurze und übersichtliche Version erstellt:

# 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
quelle
Ich denke, die Hauptversion wäre besser, denn wenn sie sudo -Kan einer anderen Stelle des Shell-Skripts aufgerufen wird, würde Ihre Version sudo: a password is requiredjede Minute nach stderr rufen.
Rockallite
@Rockallite Meinst du meine verlinkte Seite? Sie sind eigentlich gleich.
Bohr
0

Nach der sudoManpage:

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

Wenn Sie also einige sudo -vPunkte in Ihrem Setup-Skript hinzufügen , um die Sitzung zu validieren (und nicht nur zu Beginn), erhalten Sie das, was Sie möchten, da dies jedes Mal die Zeitüberschreitung erhöht (und Sie werden nur dann erneut nach dem Kennwort gefragt, wenn das Timeout ist erreicht). Das einzige Problem besteht darin, dass ein Befehl in Ihrem Skript mehr Zeit als das Timeout benötigt (selbst wenn Sie ihn direkt danach validieren, läuft das Timeout ab, bevor er für eine weitere Validierung abgeschlossen ist). Dies ist jedoch ein sehr spezifischer Fall.

Was passiert, ist, dass nur die Verwendung sudodas Zeitlimit nicht erhöht und sudo -vkeinen Befehl ausführt, sodass Sie sudo -vmehr Zeit benötigen, um die Sitzung zu validieren.

Core-Dump
quelle
Ja Danke. Das Problem ist, dass mein Sudo-Timeout näher bei 5 Minuten liegt und ich einzelne make install-Befehle habe, die weit darüber hinausgehen.
Arelius
Hmm. Gut. Abgesehen von der Verlängerung des Timeouts gibt es dann nicht mehr viel zu tun. Es gibt keine Möglichkeit, es vorübergehend festzulegen.
Coredump
0

Hier ist mein Einzeiler, basierend auf dem Inhalt von Gregory Perkins und meiner Erfahrung:

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

Oder

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

Erklärungen

  • trap "exit" INT TERM; trap "kill 0" EXIT: Hiermit wird der gesamte Prozessbaum beim Beenden oder bei SIGINT / SIGTERM geschlossen.

  • sudo -v || exit $?: Fragen Sie im Voraus nach dem Kennwort, und speichern Sie die Sicherheitsanmeldeinformationen im Cache. Führen Sie jedoch keinen Befehl aus. Wenn das Passwort nicht korrekt ist, beenden Sie es mit dem von sudo zurückgegebenen Code.

  • sleep 1: Verzögern Sie etwas, damit die Sicherheitsdaten effektiv gespeichert werden. Wenn das nächste Sudo zu früh ausgeführt wird, wird es es nicht kennen, da die Anmeldeinformationen noch nicht gespeichert wurden. Daher werden Sie erneut nach dem Kennwort gefragt.

  • while true; do sleep 60; sudo -nv; done 2>/dev/null &: Aktualisieren Sie die vorhandenen sudo-Sicherheitsanmeldeinformationen wiederholt. Beachten Sie, dass sich diese Version von der der verknüpften Version unterscheidet: Sie wird sleep 60zuerst und dann ausgeführt sudo -nv.

    • Der &Operator stellt die gesamte whileSchleife in den Hintergrund und führt sie als untergeordneten Prozess aus.

    • Das 2>/dev/nullUmleiten des Befehls stderr der whileSchleife in die Leere, sodass Fehlermeldungen, die von Befehlen innerhalb der Schleife generiert werden, verworfen werden.

    • Die -nOption sudoverhindert, dass der Benutzer zur Eingabe eines Kennworts aufgefordert wird, zeigt jedoch eine Fehlermeldung an und beendet sich, wenn ein Kennwort erforderlich ist.

    • Es gibt kein kill -0 "$$" || exitwie im verknüpften Kern, weil die ersten beiden traps den Job erledigen. Es muss 59 Sekunden lang nicht schlafen, bevor festgestellt wird, dass der übergeordnete Prozess nicht ausgeführt wird!

Rockallit
quelle