如果我做:
at -f <(echo "rm $file") now + 2 hours
效果很好
但是如果我这样做:
sudo at -f <(echo "rm $file") now + 2 hours
我得到:
at: /dev/fd/63: No such file or directory
我认为这是因为命令的处理顺序所致。有什么办法可以使用 sudo 命令来解决这个问题吗?我能想到的唯一方法是将命令放在脚本上并 sudo 该脚本(这是一个选项),但现在我想知道为什么会发生这种情况。
抱歉,如果这个问题已经在某个地方得到了回答,我只是找不到它,因为我不确定要寻找什么。
答案1
因为 shell 打开了指向 中命令的管道<(...)
,并将文件句柄传递给它运行的子进程(sudo
在本例中)。路径/dev/fd/63
是内核提供的一种方法,允许通过普通路径名访问已经打开的文件句柄。
但是,sudo
不会将句柄传递给它运行的进程(出于安全原因):默认情况下,它会关闭除 stdin、stdout 和 stderr 之外的所有文件句柄,因此最终运行的程序没有与 和 对应的文件/dev/fd/63
句柄它出错了。
您可以通过在 sudo 内的 shell 中进行替换来解决该问题:
sudo bash -c 'cat <(echo something)'
当然,这意味着内部替换也以提升的特权运行:
$ sudo bash -c 'cat <(id)'
uid=0(root) gid=0(root) groups=0(root)
标志-C
提供sudo
了另一种方式,但可能需要允许额外的配置:
-C num, --close-from=num
在执行命令之前关闭所有大于或等于 num 的文件描述符。不允许小于三的值。默认情况下,sudo 在执行命令时会关闭除标准输入、标准输出和标准错误之外的所有打开的文件描述符。安全策略可能会限制用户使用此选项的能力。当管理员启用 closefrom_override 选项时,sudoers 策略仅允许使用 -C 选项。
答案2
我假设您的意图是将cat
所有文件作为 root,您当前的ls
?
使用xargs
管道代替可能是明智的。尝试用这个:
ls | xargs sudo cat