回答:
バックグラウンドで実行されるループをセットアップして、定期的に「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)
私は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
この要点に基づいて、簡潔でクリーンなバージョンを作成しました。
# 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 &
sudo -K
シェルスクリプトの他の場所で呼び出された場合、バージョンはsudo: a password is required
毎分stderrに叫ぶので、要点バージョンの方が良いと思います。
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
、セッションを検証するためにより多くの時間を使用する必要があるということです。
上の基本骨子が提供するグレゴリー・パーキンスと私の経験では、ここに私のワンライナーです:
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
stderrのリダイレクトwhile
ループ内の任意のコマンドによって生成されたエラーメッセージが破棄されますので、無効にループを。
の-n
オプションはsudo
、ユーザーにパスワードの入力を求めることを防ぎますが、パスワードが必要な場合はエラーメッセージを表示して終了します。
何もありませんkill -0 "$$" || exit
最初の2つのので、リンクされた要旨のようにtrap
sが仕事を行います。親プロセスが実行されていないことがわかるまで、59秒間スリープする必要はありません!