我有一个用户需要将文件移动到指定日期的文件夹。我在 sudoers 文件中有一个条目,如下所示:
backupuser ALL=(ALL) NOPASSWD: /usr/bin/mv /var/lib/pgsql/base_backup/*.tar.gz /var/lib/pgsql/backups/$(date +%Y_%m_%d/)
但是,当用户运行该命令时,该命令会要求输入密码,表明未选择我在 sudoers 文件中输入的命令。
我是否缺少一些转义字符,我尝试在 (, ), % 前面使用 \ 进行转义,但当我尝试这样做时出现语法错误。
如果您需要更多信息,请告诉我。
答案1
这都是关于评估顺序的。当用户执行这样的命令时
sudo mv /var/lib/pgsql/base_backup/*.tar.gz /var/lib/pgsql/backups/$(date +%Y_%m_%d/)
这评估顺序通配符和$(…)
扩展在命令执行之前由 shell 处理。如果您有两个源文件one.tar.gz
和two.tar.gz
,并且今天的日期是 2024 年 4 月 25 日,您最终会得到以下命令:
sudo mv /var/lib/pgsql/base_backup/one.tar.gz /var/lib/pgsql/base_backup/two.tar.gz /var/lib/pgsql/backups/2024-04-25/
现在虽然sudoers
文件确实理解*
为通配符(但远比 shell 更自由- 请注意!),该$(…)
部分无法理解,因此除了 18 个字符的文字序列之外不会匹配。因此,结果命令被拒绝sudo
。
您最好创建一个脚本并由备份用户执行该脚本。例如,放置在只能由 root 修改的地方:
#!/bin/sh
# Move backup files to a date-based directory
########################################################################
#
today=$(date +%Y_%m_%d)
ss=0
src='/var/lib/pgsql/base_backup'
dst="/var/lib/pgsql/backups/$today"
if [ ! -d "$src" ]
then
echo "ERROR: Missing source: $src" >&2
ss=1
fi
if [ ! -d "$dst" ] || [ ! -w "$dst" ]
then
echo "ERROR: Missing or inaccessible destination: $dst" >&2
ss=1
fi
if [ "$ss" -gt 0 ]
then
exit "$ss"
fi
mv -f -- "$src"/*.tar.gz "$dst/"
exit