web-dev-qa-db-ja.com

インストールスクリプトの実行中に一時的にSudoのタイムアウトを増やす

一連のソフトウェアをインストールするスクリプトを記述しようとしています。すべてをrootとして実行する必要がないようにしたいので、パスワードの入力を求めてから、インストールについては、Sudoまたはsuを使用して、必要なときに権限を取得します。

Sudo -v toスクリプトの最初にパスワードの入力を要求し、後で通常どおりSudoを使用します。これは、タイムアウトを引き継ぐ単一のインストールに到達するまではうまく機能します。

タイムアウトを永続的に増やす必要はありません。現在のセッションでのみSudoのタイムアウトを増やす方法はありますか?

22
Arelius

バックグラウンドで実行されるループを設定して定期的に「Sudo -v」を実行することができます。もちろん、スクリプトが終了するとループが完全に終了します。したがって、2つのプロセス間に何らかのタイプの通信が必要です。 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)
8
michael

私は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
9
Gregory Perkins

これに基づいて Gist を使用して、簡潔でクリーンなバージョンを作成しました。

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

GistGregory Perkins によって提供されるベースと私の経験、これが私の1行です:

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の実行が早すぎる場合は、資格情報がまだ保存されていないため、Sudoはそれを認識せず、パスワードを再度要求します。

  • while true; do sleep 60; Sudo -nv; done 2>/dev/null &:既存のSudoセキュリティ認証情報を繰り返し更新します。このバージョンは、リンクされたGistのバージョンとは異なります。最初にsleep 60、次にSudo -nvを実行します。

    • &演算子は、whileループ全体をバックグラウンドに配置し、子プロセスとして実行します。

    • 2>/dev/nullは、whileループのstderrをvoidにリダイレクトするため、ループ内のコマンドによって生成されたエラーメッセージは破棄されます。

    • Sudo-nオプションは、ユーザーにパスワードを要求することを防ぎますが、パスワードが必要な場合はエラーメッセージを表示して終了します。

    • 最初の2つのtrapsが機能するため、リンクされたGistのようなkill -0 "$$" || exitはありません。親プロセスが実行されていないことがわかるまで、59秒間スリープする必要はありません。

1
Rockallite

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.

したがって、セットアップスクリプトのより多くのポイントにSudo -vを追加してセッションを検証すると(最初だけでなく)、タイムアウトが増えるたびに(必要なだけ)、必要な結果が得られると思いますタイムアウトに達した場合、パスワードを再入力します)。唯一の問題は、スクリプトにタイムアウトよりも時間がかかるコマンドがある場合です(そのため、タイムアウトの直後に検証しても、タイムアウトが完了してから次の検証が完了するまでは)、これは非常に特殊なケースです。

Sudoを使用してもタイムアウトは増加せず、Sudo -vはコマンドを実行しないため、セッションを検証するためにSudo -vをさらに使用する必要があります。

0
coredump