在 shell 脚本中使用 sudo 命令是好习惯还是坏习惯?一个优点是,如果用户以非 root 身份运行脚本,则系统会要求用户输入密码,而不会导致脚本失败。另一方面,如果用户最近使用 sudo 运行了命令,则脚本将隐式以 root 身份运行命令,这可能不是用户所期望的。
以下是一个例子:
$ cat foo1
#!/bin/sh
sudo bar #implicit sudo
$ ./foo1
$ cat foo2
#!/bin/sh
bar
$ sudo ./foo2 #explicit sudo
答案1
使用 sudo 是总是这是一种很好的做法。但是,有一些方法可以更好地使用 sudo。一种方法是明确允许特定命令以提升的权限运行。
以下仅允许“用户”组中的人员无需密码执行命令 foo1。
%users ALL=(ALL) NOPASSWD: /full/path/to/foo1
但是,除非用户输入正确的密码,否则它将不允许执行上述示例中的 foo2。
此外,通常最好将 sudo 配置为需要用户密码而不是 root 密码(我此时忘记了配置选项),并且不要包含任何可允许用户提升其权限的条目,例如:
ALL ALL=(ALL) ALL
或者
%users ALL=(ALL) ALL
使用 wheel 组或类似组来升级任何命令是一种很好的做法。最后,最好将 root 密码锁在保险箱中,除非发生可怕的事情,否则永远不会被任何人使用。
答案2
/简短意见
我个人认为,如果您在运行脚本之前没有查看它,那么无论发生什么副作用,大部分都是您的错(sudo
例如,运行的命令不会提示您),但与此同时,我知道每次解析和理解整个脚本都很困难。总的来说,我更喜欢一种可以平衡便利性和安全性的混合策略。
/结束意见
请记住,您始终可以sudo -k
在调用脚本之前运行,以要求第一次隐式sudo
调用提示输入您的密码,但除非它也在sudo
脚本内的每个命令之后运行,否则它只会提示您第一次调用sudo
。
有几种方法可以实现安全、合理的脚本,仅在必要时使用 sudo,其中一些方法比其他方法更令人讨厌/不明智。这篇文章概述了一些示例/选项,我将进一步阐述。https://bitmingw.com/2017/01/22/use-sudo-in-scripts/
您可以运行整个脚本,sudo
正如您所描述的那样,它是“显式的”,但这也意味着脚本中的所有命令都以 root 身份运行,如果它写得不好,或者您忘记了$USER
脚本内部可能会更改为root
,而您需要使用,$SUDO_USER
那么您可能会陷入困境。我过去曾不小心这样做过,然后发生了奇怪而可怕的事情,然后您(和我)最终用if [ $EUID -eq 0 ]; then echo "Don't run as root!"; fi
或相反的方式保护您的脚本-gt 0
,您必须记住在您编写的每个脚本中放置一个保护程序(或学习 SaltStack/Puppet/Chef 等配置管理工具,它们可以为您自动执行其中的一些操作)。
sudo somescript.sh
我更喜欢使用的选项是临时运行sudo
无限缓存时间,这样您运行的其他 sudo 命令就不需要重新提示(或者可能任何人,具体取决于您的设置方式)。理想情况下,您应该在脚本的早期放置一个正确自动化和测试的功能(或包含您的“cache_sudo.sh”脚本),然后在脚本退出(sudoers.d
终止/完成/错误)后立即删除无限超时启用文件trap
,然后sudo -k
在删除文件后使会话/令牌过期。请参阅这个答案作为测试的示例,仅当有效时才添加文件。
这是手动版本,请不要将其放入您的脚本中。
sudo visudo -f /etc/sudoers.d/infinite_cache_myuser
#Add next line to the file
Defaults:YOUR_USER_NAME timestamp_timeout=-1
无限缓存的好处是,在您的脚本中,您可以仅使用 sudo 提升需要 root 权限的命令,而不必使用su $MY_REGULAR_USER some_command
或sudo -u $MY_REGULAR_USER some_command
为每个命令“降级”所有其他命令。(如果有一种不那么痛苦且并非完全不安全的方式来编写仅在必要时提升权限,我真的不喜欢毫无意义地重复代码来降低权限)。
减少重复代码的一种方法是定义一个简短的命令“前缀”,该前缀添加sudo
或取决于脚本是否使用或使用内部su $MY_USER
运行。sudo ./myscript.sh
./myscript.sh
sudo
您可以编写一条sudoers
规则来允许在不提示密码的情况下执行目标脚本sudo
,但我认为这与第一个选项一样糟糕,如果您想从以非 root 用户身份运行的 cron 作业运行 sudo 但需要更改需要 root 或其他用户才能执行的操作,它只会略有帮助,但您需要阅读man sudoers
以了解允许用户模仿另一个用户的语法。
# Customize line below and add to /etc/sudoers or /etc/sudoers.d/my_script_runner
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/abs/path/to/your/script
您还可以仅对需要密码的命令允许无密码 sudo,这允许您以非 root 身份运行脚本并仍然访问这些命令。
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get update
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get upgrade
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/usr/bin/updatedb
这个选项可能是我继无限缓存技巧之后的第二选择。缺点是每次找到需要 root 权限的新命令时,您都要编辑 sudoers 文件,而不是仅仅能够sudo
在脚本中的命令前面添加。优点是您只sudo
在必要时允许无密码,并且您仍然可以要求其他命令输入密码,sudo
因此更加安全。