非交互式脚本中的sudo


9

我有一个执行三个功能的脚本:A && B && C

功能B需要运行一个超级用户,而AC没有。

我有几种解决方案,但都不令人满意:

  1. sudo整个脚本: sudo 'A && B && C'

    如果不需要AC以超级用户身份运行似乎是个坏主意

  2. 使脚本具有交互性: A && sudo B && C

    我可能必须输入密码,但是我希望脚本是非交互式的,因为每个功能可能要花一些时间,并且我不希望脚本等待我。好吧,这也是为什么它首先是脚本的原因,所以我不必看着它运行。

  3. 愚蠢的解决方案: sudo : && A && sudo -n B && C

    首先,先执行无操作操作似乎很愚蠢sudo,而且我还必须交叉指责A不会花更多的钱$sudo_timeout

  4. 假设的解决方案(希望您告诉我它的存在):

    sudo --store-cred 'A && sudo --use-cred-from-parent-sudo B && C'

    这会在一开始提示您输入密码,然后仅在需要时使用该凭据。

您对这一切有何看法?对于这个问题没有解决方案,我感到非常惊讶,因为我认为这是一个非常普遍的问题(关于make all && sudo make install


3
您可以制作一个使用sudo执行的脚本,但在脚本中使用显式执行AC部分su -l some_non_priviliged_user。没有超时问题,也没有对A和C的特权。我认为4不可能,sudo对于用户来说似乎是“全局状态”。
Anthon

Answers:


7

我认为你能做的最好的事情就是与启动脚本sudo,然后启动你想作为一个普通用户显式运行的进程su usersudo -u user

#!/usr/bin/env bash

## Detect the user who launched the script
usr=$(env | grep SUDO_USER | cut -d= -f 2)

## Exit if the script was not launched by root or through sudo
if [ -z $usr ] && [ $USER = "root" ]
then
    echo "The script needs to run as root" && exit 1
fi

## Run the job(s) that don't need root
sudo -u $usr commandA

## Run the job that needs to be run as root
commandB

9

将脚本添加到/etc/sudoers具有NOPASSWD属性的文件中,这样就可以在不提示输入密码的情况下运行脚本。您可以将此绑定到特定的用户(或一组用户),或者允许它与sudo系统上的任何人一起运行。

名为的脚本的示例行/usr/local/bin/bossy可能看起来像这样

ALL ALL = (root) NOPASSWD: /usr/local/bin/bossy

然后你会用这样的东西

A && sudo bossy && C

对于此示例,我假设PATH包括/usr/local/bin。如果不是,则只使用脚本的完整路径,即sudo /usr/local/bin/bossy


支持最安全的方法。
eyoung100

0

您可能要同时使用!requiretty选项sudo和中的NOPASSWD选项。但是请记住,这会降低安全性。


1
当问题被定义为不想要的脚本是交互式的,#2 /etc/sudoers项为用户执行命令BNOPASSWD是正确的答案。
安德鲁(Andrew)

那就是“你可以做X或Y”,那是“你可以做X和Y”。只有两者都能解决问题。也许我应该重新措辞。
史蒂夫·威尔斯

0

基于我对sudo进行预授权的答案(因此可以稍后运行),编写两个脚本:

  • ABC_script

    #!/bin/sh
    sudo -b ./B_script
    A  &&  > A_is_done
    while [ ! -f B_is_done ]
    do
            sleep 60
    done
    rm -f B_is_done
    C
  • B_script

    #!/bin/sh
    while [ ! -f A_is_done ]
    do
            sleep 60
    done
    rm -f A_is_done
    B  &&  > B_is_done

运行./ABC_script

  • 它将运行sudo -b ./B_script。这要求输入密码(运行后立即输入ABC_script)。假设输入了正确的密码,它产生B_scriptb ackground(因为-b被指定)为根。这似乎等效于sudo sh -c "./B_script &"
  • B_script开始与并行进行异步运行ABC_script。  B_script测试是否存在名为的文件,A_is_done 并循环播放直到出现。
  • 并行ABC_script运行A。如果A成功完成,脚本将创建一个名为的文件A_is_done
  • ABC_script然后测试是否存在一个名为的文件,B_is_done 并循环播放直到出现。
  • 并行 B_script检测A_is_done循环的存在并跳出循环。它删除该A_is_done文件并运行B。请记住,B_scriptB以root身份运行,因此它以root身份运行。如果B成功完成,脚本将创建一个名为的文件B_is_done并退出。
  • 并行 ABC_script检测B_is_done循环的存在并跳出循环。删除B_is_done文件。记住,B_script以root身份运行,所以root B_is_done拥有它,因此您要rm -f避免收到确认请求。 ABC_script然后运行C并退出。

进一步完善的注意事项:

  • ABC_script应该B_script遵循绝对路径而非绝对路径./
  • 而不是A_is_doneB_is_doneABC_script应该可能会生成随机的唯一文件名。
  • 如果正在等待的程序已完成但失败,则需要为正在等待的脚本提供通知。(现在,如果A失败,则两个脚本都将进入无限等待循环。)这就像更改一样简单

    A  &&  > A_is_done

    A; echo $? > A_is_done

    然后修改自旋等待以读取X_is_done文件,如果包含0,则继续操作,否则退出。


-3

没话说 用很多行。

if A; then

    if sudo B ; then
        C
    fi
fi

如何解决我的任何担忧?问题不相关&&
Antoine Pelisse

当第一个命令失败时,&&停止执行。if语句更详细地说明了这一点。我的观点是要完成您的工作,即使它不是很漂亮。
罗伯特·雅各布斯

1
这仅是选项2的详细版本A && sudo B && C。就像安托万在问题中解释的那样;这直到A完成后才要求输入密码,并且他不想等待密码或让脚本等待他。
斯科特
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.