![在 Bash 脚本中使用 sudo 的最佳实践](https://linux22.com/image/1148991/%E5%9C%A8%20Bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E4%BD%BF%E7%94%A8%20sudo%20%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.png)
我有一个长期运行的 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
执行,command1
command2
没有密码验证:
reguser machine1 root = NOPASSWD: /usr/local/command1, /usr/local/command2
但请阅读每一个man -k sudo
细节。
答案3
也许这可以帮助:
chmod 775 你的脚本.sh
然后您可以在脚本内部使用 sudo(无需密码提示),并且不能在脚本内部对其他命令使用 sudo。