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


11

我有一个运行时间很长的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失败(例如,由于密码无效),则脚本的其余部分仍将执行。

方法2:使用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的情况下运行。


4
这很少需要。在大多数情况下,sudo如果需要提升权限,只需运行即可。但是切换su username -c到运行没有意义echo。换句话说,这听起来像[XY]。您能否编辑和解释您的脚本将实际执行的操作以及为什么您觉得需要如此频繁地切换用户?
terdon '17

1
@ElderGeek您粘贴了错误的链接吗?这似乎似乎无关。这可能是如何在脚本中运行“ sudo”命令的副本但我希望OP可以解释更多。
terdon

@terdon似乎是这样。打扫干净。
年长者极客

这只是一个示例脚本。我不想在这里粘贴200多个行脚本。我将编辑答案以获取更多详细信息。
达卡龙

您是否考虑过validate选项(在中进行了介绍)man sudo-v, --validate '更新用户的缓存凭据,必要时对用户进行身份验证。对于sudoers插件,默认情况下,这会将sudo超时再延长15分钟,但不会运行命令。并非所有的安全策略都支持缓存的凭据。(如果您经常运行它,则sudo身份验证不应超时。)
sudodus

Answers:


5

关于方法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主机machine1来执行command1,并command2作为根,没有密码验证:

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

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


0

也许这可以帮助:

chmod 775 yourscript.sh

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


我担心那行不通。chmod 775仅允许您执行文件,而不更改正在执行文件的用户或其权限。
达卡龙
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.