使用sudo时如何使用tee

3

UBuntu 16.04

Bash 4.4

在4-bash-update.sh的第158行:

cd "$drive00" && sudo -H -u myuser bash -c "timeout 2s ./binaryfile -gentoken" > "${save_log_dir}"/update-"${now}".log;
                                                                              ^-- SC2024: sudo doesn't affect redirects. Use ..| sudo tee file

我尝试了几次,每次我的文件都被删除了。

你说的“被吃掉”是什么意思?该命令应该截断输出文件——如果你不想这样,那就需要用>>而不是>。 (很明显,按照原来的写法,代码尝试使用原始的、预先sudo特权打开输出文件,但如果文件被“吃掉”,这意味着实际上有足够的写入权限来截断它,因此首先要解决的问题是你想用tee解决什么问题)。 - Charles Duffy
1个回答

5

您无需使用tee,只需将重定向放在使用bash -c执行的命令内部:

sudo -H -u myuser bash -c 'timeout 2s ./binaryfile -gentoken > "$1"' _ "${save_log_dir}/update-${now}.log"

如果你在外部进行重定向,你的原始shell会尝试打开文件,但它没有权限。把它放在bash参数内会在目标用户的shell中以他们的权限执行。命令行中的_是shell中$0参数的虚拟值。你需要该占位符才能将文件名作为$1提供。

同意;如果您有sudo bash的权限,那么您可能不需要同时使用sudo tee。一些环境通过sudo限制了shell访问,而在这种情况下,sudo bash不是一个选项。此外,如果文件写入是唯一需要sudo访问权限的部分,则以无需sudo运行生成输出的命令并将其管道传输到sudo tee [-a] filename更符合最小特权原则。 - Mark Reed
2
更好的做法是使用 sudo -H -u myuser bash -c 'timeout 2s ./binaryfile -gentoken >"$1"' _ "${save_log_dir}/update-${now}.log",这样你就不会将数据(文件名)替换为代码(sh -c 的参数)。当然,OP 可能控制着 save_log_dirnow 的值,但最好养成良好的习惯,以备后来操作上传/不受信任/用户提供的文件名时。 - Charles Duffy
@CharlesDuffy 下划线 _ 的用途/目的是什么? - nbari
@nbari,它是一个占位符,用于 $0,这样以下参数就变成了 $1 - Charles Duffy
1
@Barmar,...我理解的是单引号是对我的评论做出的回应?(尽管没有编辑历史记录,但我不记得之前看到过它们)。如果是这样,它们实际上并不能防止注入攻击;文件名完全可以包含一个字面上的 ' 字符。考虑 touch $'hello\'$(rm -rf ~)\'$(rm -rf ~)',创建一个名称,无论是否存在这样的引号,都将执行注入。 - Charles Duffy
@CharlesDuffy,它们在我的原始答案中,不确定为什么你没看到。我会使用您的版本。 - Barmar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接