98 lines
2.5 KiB
Bash
Executable File
98 lines
2.5 KiB
Bash
Executable File
#!/bin/bash
|
||
# 为指定用户配置某命令的免密 sudo(写入 /etc/sudoers.d/)
|
||
# 用法: sudo nosudo <user> <command>
|
||
# 示例: sudo nosudo xuser docker
|
||
|
||
set -euo pipefail
|
||
|
||
usage() {
|
||
cat <<'EOF'
|
||
用法: sudo nosudo <user> <command>
|
||
|
||
为 <user> 配置对 <command> 的免密 sudo(NOPASSWD)。
|
||
|
||
示例:
|
||
sudo nosudo xuser docker
|
||
sudo nosudo xuser /usr/bin/systemctl
|
||
|
||
说明:
|
||
- 每个命令单独一个文件(nosudo-<user>-<命令名>),可多次执行、互不覆盖
|
||
例如 nosudo xuser kubectl 与 nosudo xuser helm 会各写一条规则,同时生效
|
||
- 仅允许免密执行解析到的那个可执行文件路径(含子命令参数仍受 sudo 规则约束)
|
||
- 对 docker,更推荐: sudo docker-group <user>(无需 sudo 即可用 docker)
|
||
- 删除规则: sudo rm /etc/sudoers.d/nosudo-<user>-<name>
|
||
EOF
|
||
exit 1
|
||
}
|
||
|
||
[[ "${1:-}" == "-h" || "${1:-}" == "--help" ]] && usage
|
||
[[ $# -eq 2 ]] || usage
|
||
|
||
if [[ $EUID -ne 0 ]]; then
|
||
echo "错误: 请使用 sudo 运行,例如: sudo $0 $*"
|
||
exit 1
|
||
fi
|
||
|
||
if [[ ! -d /etc/sudoers.d ]]; then
|
||
echo "错误: 未找到 /etc/sudoers.d(当前系统可能不支持此方式)"
|
||
exit 1
|
||
fi
|
||
|
||
user="$1"
|
||
cmd="$2"
|
||
|
||
if ! id "$user" &>/dev/null; then
|
||
echo "错误: 用户不存在: $user"
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "$cmd" == /* ]]; then
|
||
cmd_path="$cmd"
|
||
else
|
||
cmd_path="$(command -v "$cmd" 2>/dev/null || true)"
|
||
fi
|
||
|
||
if [[ -z "$cmd_path" || ! -x "$cmd_path" ]]; then
|
||
echo "错误: 找不到可执行文件: $cmd"
|
||
echo "提示: 可先安装该命令,或传入绝对路径,例如 /usr/bin/docker"
|
||
exit 1
|
||
fi
|
||
|
||
name="$(basename "$cmd_path")"
|
||
file="/etc/sudoers.d/nosudo-${user}-${name}"
|
||
|
||
if [[ -f "$file" ]]; then
|
||
if grep -qF "NOPASSWD: ${cmd_path}" "$file" 2>/dev/null; then
|
||
echo "已存在相同规则: $file"
|
||
exit 0
|
||
fi
|
||
fi
|
||
|
||
tmp="$(mktemp)"
|
||
trap 'rm -f "$tmp"' EXIT
|
||
|
||
cat >"$tmp" <<EOF
|
||
# Managed by nosudo ($0)
|
||
# user=$user command=$cmd_path
|
||
${user} ALL=(ALL) NOPASSWD: ${cmd_path}
|
||
EOF
|
||
|
||
if ! visudo -cf "$tmp" >/dev/null; then
|
||
echo "错误: sudoers 语法校验失败"
|
||
visudo -cf "$tmp" || true
|
||
exit 1
|
||
fi
|
||
|
||
install -m 0440 -o root -g root "$tmp" "$file"
|
||
|
||
echo "已写入: $file"
|
||
echo "内容: ${user} ALL=(ALL) NOPASSWD: ${cmd_path}"
|
||
echo ""
|
||
echo "验证(切换到该用户后):"
|
||
echo " sudo -u ${user} sudo -n ${cmd_path} version 2>/dev/null || sudo -u ${user} sudo -n ${cmd_path} --help | head -1"
|
||
if [[ "$name" == "docker" ]]; then
|
||
echo ""
|
||
echo "提示: 若希望直接运行 docker(不用 sudo),请执行:"
|
||
echo " sudo docker-group ${user}"
|
||
fi
|