在 Bash 脚本中使用 sudo 的最佳实践

在 Bash 脚本中使用 sudo 的最佳实践

我有一个长期运行的 bash 脚本,其中一些命令需要以 root 身份运行,而大多数命令需要在 sudo 之前以普通用户身份运行,因为这会弄乱文件所有权等。

我想到了一些方法,但每个方法都存在一些问题

方法 1:在文件内使用 sudo

#!/bin/bash
sudo echo "I must be run by root"
touch needsToBeOwnedByUser1
echo "needs to be run by user"
sleep 1000
sudo echo "I, again, must be run by root"

从代码编写方式来看,这看起来不错。sudo写在实际上需要由 root 运行的几个语句之前,但如果每次sudo调用之间的时间太长,sudo则会再次要求输入密码。此外,如果第一次执行sudo失败(例如由于密码无效),脚本的其余部分仍会执行。

方法二:使用 sudo 调用文件,然后在需要的时候改回原来的用户

#!/bin/bash
echo "I must be run by root"
su username -c 'touch needsToBeOwnedByUser1'
su username -c 'echo "needs to be run by user"'
su username -c 'sleep 1000'
echo "I, again, must be run by root"

这也很糟糕,因为我需要su username -c在几乎每一行前面添加。此外,也sudo可以找到原始用户名,但很麻烦。

有没有更好的办法?

编辑:我在这里只发布了一些小而无意义的脚本来展示我所说的内容。在实际脚本中,我有一些需要 sudo 的行(启动和停止服务),有些行即使有 sudo 也无所谓,还有相当多的行确实需要在没有 sudo 的情况下运行。

答案1

对于方法2,使用函数更简单。例如:

#!/bin/bash

func(){
    echo "Username: $USER"
    echo "    EUID: $EUID"
}

export -f func

func
su "$SUDO_USER" -c 'func'

$SUDO_USER是 sudoer 的用户名。您也可以使用$(logname)它。

在我的计算机上运行:

$ sudo bash test.sh
[sudo] password for wja: 
Username: root
    EUID: 0
Username: wja
    EUID: 1000

答案2

通过阅读man sudoers,我们可以看到:

 PASSWD and NOPASSWD

   By default, sudo requires that a user authenticate him or herself
   before running a command.  This behavior can be modified via the
   NOPASSWD tag.  Like a Runas_Spec, the NOPASSWD tag sets a default for
   the commands that follow it in the Cmnd_Spec_List.  Conversely, the
   PASSWD tag can be used to reverse things.  For example:

   ray     rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm

   would allow the user ray to run /bin/kill, /bin/ls, and /usr/bin/lprm
   as root on the machine rushmore without authenticating himself. 

因此,您可以允许regular主机以 root身份machine1执行,command1command2没有密码验证:

reguser machine1 root = NOPASSWD: /usr/local/command1, /usr/local/command2  

但请阅读每一个man -k sudo细节。

答案3

也许这可以帮助:

chmod 775 你的脚本.sh

然后您可以在脚本内部使用 sudo(无需密码提示),并且不能在脚本内部对其他命令使用 sudo。

相关内容