当您尝试在没有文件写入权限的情况下修改文件时,会出现错误:

> touch /tmp/foo && sudo chown root /tmp/foo
> echo test > /tmp/foo
zsh: permission denied: /tmp/foo


Sudoing无效,因为它以root身份运行命令,但是Shell会处理重定向标准输出并按照您的方式打开文件:

> sudo echo test > /tmp/foo
zsh: permission denied: /tmp/foo


是否有一种简单的方法将标准输出重定向到您没有写权限的文件除了以root身份打开外壳并以这种方式操作文件之外?

> sudo su
# echo test > /tmp/foo


评论

从StackOverflowstackoverflow.com/questions/82256/…中回答类似的问题。

您如何不拥有在tmp中创建的文件的权限?是因为umask吗?

@ k961我用chown更改了所有者;这只是一个例子

#1 楼

是的,使用tee。所以echo test > /tmp/foo成为

echo test | sudo tee /tmp/foo


您还可以附加(>>

echo test | sudo tee -a /tmp/foo


评论


Tee也将输出到stdout;有时您不希望内容填满屏幕。要解决此问题,请执行回声测试| sudo tee / tmp / foo> / dev /空

– Shawn J. Goff
2010-12-14 15:20

您将如何使用Heredoc?

–user149572
16-11-19在2:54

#2 楼

echo的输出(例如> shell重定向操作符)的输出替换文件的内容。

echo test | sudo dd of=/tmp/foo


要写入文件(尽管在开始时,可以使用seek以不同的偏移量输出)而不会被截断(例如1<> Bourne shell运算符):

echo test | sudo dd of=/tmp/foo conv=notrunc


使用GNU >>附加到文件(例如dd) :

echo test | sudo dd of=/tmp/foo oflag=append conv=notrunc


另请参阅GNU ddconv=excl避免破坏现有文件(例如POSIX shell中的set -o noclobber)和相反的conv=nocreat(仅更新现有文件) )。

评论


聪明!这减轻了进行回声测试的需要| sudo tee / tmp / foo> / dev / null放弃输出。

–亚当·卡兹(Adam Katz)
2015年1月14日23:52

我可能不得不把它拿回来; dd对此是不可靠的,除非您使用仅GNU专用的晦涩选项iflag = fullblock oflag = fullblock,否则将使此答案显得格格不入。我会坚持发球。

–亚当·卡兹(Adam Katz)
15年1月16日在6:32

dd是可靠的,bs = 1

–umeboshi
2015年1月25日,3:50

@umeboshi但是只有当您有足够的经验确切地知道您在做什么时,它才是可靠的。如果只犯了一个小错误,福特(Fordd)可能会相当危险(如果不是说:毁灭性的话)。因此,对于新用户,我宁愿推荐使用tee方法。

–syntaxerror
16 Jan 29 '17:38



@AdamKatz,仅在dd of = file的情况下(没有count / skip ...),这是可靠的。 iflag = fullblock是不需要的,因为这里dd在输出上写入它在输入上读取的内容。它是否不是完整块并不重要。

–StéphaneChazelas
17年9月12日上午11:30

#3 楼

tee可能是最好的选择,但是根据您的情况,这样的事情就足够了:

sudo sh -c 'echo test > /tmp/foo'


评论


3个问题:用eval代替简单的sh -c; -i,这将更改您的工作目录;以root用户身份运行整个命令,这可能会改变其行为或可能带来不必要的风险。为什么这会引起反对?

–user601
2010年8月31日上午10:38

您没有这样做,但是它具有误导性,通常很糟糕,甚至可能很危险。

–user601
2010年8月31日在20:24

#4 楼

虽然我同意,但是| sudo tee是规范的方式,有时sed(在这里假设GNU sed)可以工作:

cat sudotest 
line 1

sudo sed -i '1iitest' sudotest && cat sudotest 
itest
line 1

sudo sed -i '$aatest' sudotest && cat sudotest 
itest
line 1
atest


-i修改文件到位。 1i表示在第1行之前插入。$a表示在最后一行之后附加。

或复制到xclipboard:

somecommand | xclip
sudo gedit sudotest
move cursor to desired place, click middle mouse button to insert, save


评论


这句话像中国古代的谜语。看不清楚这是怎么得到这么多赞成的。 (时)

–syntaxerror
16年1月29日在17:36

@syntaxerror:先生,对不起,我不是英语母语人士。如果您指定不清楚的地方,我可以尝试改善答案。与Gert的65票相比,似乎4票也没有那么多,你不觉得吗?

–用户未知
16年1月30日,下午1:35

好吧,我会对4 :-D非常满意。您的英语一点也不差。它只是用一种简洁的技术书呆子说话。我必须猜你是编码员。彼此之间的编码人员将以这种方式完全理解自己,但是非编码人员必须认为它的措辞就像...所说的。

–syntaxerror
16年1月31日在20:22



请注意,sed -i实际上不会在原位修改文件-它会创建一个临时文件并在退出时重命名。因此,您将无法在原始文件上执行tail -f ...之类的操作,并在管道运行时使用sed -i ...查看输出

–安德鲁·亨利(Andrew Henle)
18-3-14在10:24



@AndrewHenle:是的,因为大小可能会增加或缩小,而且对于大多数sed调用来说可能就是这种情况,而且-afaik-甚至无法写入SSD上的同一位置,这只是伪的“就地”操作。作为非英语母语者,我是否可以要求简短表达,这不太可能会被误解?只是-i创建一个同名的新文件,还是有一些更紧凑的文件?我想我喜欢就位,因为它解释了i。 gnu-sed联机帮助页也将其称为就地,而长标志是--in-place。

–用户未知
18-3-14在10:30



#5 楼

我一直在思考类似问题的想法,并提出以下解决方案:


sudo uncat其中uncat是读取标准输入并将其写入的程序到在命令行上命名的文件,但我尚未编写uncat
sudocat我尚未编写的sudoedit的变体,它使sudo catsudo uncat更加整洁。

或者将sudoedit与带有外壳脚本的EDITOR一起使用的小技巧

#!/bin/sh
# uncat
cat > ""


,可以将其作为|sudo ./uncat file| EDITOR=./uncat sudoedit调用,但具有有趣的副作用。 br />


评论


cat需要合并一个文件列表,因此uncat应该合并一个文件列表。它必须使用魔术来决定每个文件中放多少。备用名称包括狗,目标文件,重定向。

–ctrl-alt-delor
2015年4月15日14:51



我想不出开球后为什么会想要解脱的任何原因。

–通配符
2015年9月29日在9:26

好吧,tee具有一个琐碎的缺点,那就是将其stdin写入其stdout-通过将stdout重定向到/ dev / null可以轻松地减轻这种情况。其他选择包括ddof = / tmp / foo(在另一个答案中提到),它将状态信息写入stderr,以及cp / dev / stdin / tmp / foo。

–斯科特
16-2-17在14:44

#6 楼

使用moreutils包装中的海绵。它的优点是它不会写到stdout。

echo test | sudo sponge /tmp/foo


使用-a选项附加到文件而不是覆盖它。

评论


我不确定不写stdout有什么好处,但是如果有问题,您可以将输出重定向到/ dev / null

– Michael Mrozek
16 Dec 18'在4:41

当然,我可以重定向到/ dev / null,但是该命令更易于阅读和键入,而无需重定向。不写到stdout的好处是我的终端没有垃圾。

–HontváriLevente
16 Dec 18'在22:48

我不会安装软件包来避免重定向,但是我经常使用海绵,因此它已经存在。

–HontváriLevente
16 Dec 18 '22:50

#7 楼

错误是由外壳程序执行的顺序引起的。

重定向在外壳程序执行sudo之前就已进行了处理,因此,该操作是在您当前使用的用户权限下完成的。由于您没有写权限来创建/截断重定向目标,因此从外壳程序会收到permission denied错误。

解决方案是确保在给定的标识下创建输出文件。通过sudo给您,例如与tee

$ generate_output | sudo tee target_file