在安装脚本期间临时增加sudo的超时


22

我正在尝试编写一个脚本,该脚本将安装大量软件,并且我不想以方式运行所有程序root,因此,我希望能够提示输入密码,然后使用sudo或进行安装。su在我需要特权时获得特权。

我正在做一个sudo -v提示,要求在脚本开头输入密码,然后稍后再正常使用sudo。直到我安装了一个超时的单机安装,这才有效。

我宁愿不必永久增加超时时间。有没有一种方法可以仅在当前会话中增加sudo的超时时间?

Answers:


8

您可以设置一个在后台运行的循环,以定期执行“ sudo -v”,当然,要诀就是让循环在脚本终止时完全终止。因此,两个过程之间必须进行某种类型的通信。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)

9

我喜欢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

6
还有一个更简洁的解决方案:gist.github.com/3118588
Gregory Perkins

这怎么没有1000多个投票?简洁的版本很棒。(但我认为,一个更好的例子会有所帮助。)
MountainX for Monica Cellio

3

基于这个要点,我制作了一个简洁明了的版本:

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

我认为gist版本会更好,因为如果sudo -K在shell脚本的其他位置调用该版本,则您的版本sudo: a password is required每分钟都会对stderr 吼叫。
Rockallite

@Rockallite你的意思是我的链接要点吗?它们实际上是相同的。
玻尔

0

根据sudo手册页:

   -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更多时间来验证会话。


是的,谢谢。问题是我的sudo超时接近5分钟,而且我只有一个make install命令,该命令已经远远超过了。
2011年

嗯 好。然后,除了增加超时时间外,没有其他事情要做。无法暂时设置。
coredump

0

根据格雷戈里·珀金斯Gregory Perkins)提供的要旨和我的经验,这是我的一句话:

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重定向的标准错误while循环到空隙,所以通过在循环内的任何命令生成的错误消息将被丢弃。

    • 所述-n的选项sudo,如果需要密码防止它提示用户输入密码,但显示错误消息并退出。

    • kill -0 "$$" || exit链接的要点中没有,因为前两个trap将完成工作。在确定父进程未运行之前,它无需休眠59秒钟!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.