我的猜测如下:
echo "Generating some text" | su - -c cat >/output/file
但su
说:
su: must be run from a terminal
你会怎么办?
答案1
sudo
支持这一点。
$ echo hello world | sudo cat
SUDO password:
hello world
不同之处在于,它sudo
要求您提供用户密码,而不是root
(目标用户)密码。但是,如果您愿意,可以使用中的targetpw
(orrunaspw
或rootpw
) 指令更改此行为sudoers.conf
。
然而,阅读您想要执行的操作,虽然这解决了权限升级问题,但它不会达到您的预期。这意味着/output/file
不会以 root 用户身份创建,而是以您的用户身份创建/修改。
原因是 shell 输出重定向是在调用任何命令之前完成的。因此 shell 打开/output/file
,然后将打开的文件传递给su
/ sudo
(因此,传递给cat
)。
但是,您可以使用tee
它来执行此操作,因为该tee
实用程序将自行打开文件。
echo "hello world" | sudo tee /output/file >/dev/null
基本上tee
将输出复制到/output/file
STDOUT 中,但是 STDOUT 被重定向到/dev/null
.
你还可以这样做:
echo "hello world" | sudo sh -c 'cat > /output/file'
...这不太神秘。
答案2
只是让你知道 - 你不限于每个命令|pipe
:
this happens | then this | { then ; all of ; this too ; } | before this
所有这些进程都是同时调用的 - 但它们|pipe
在实际执行任何操作之前都会等待它们之前 - 只要它们|pipe
完全读取了,就是这样。因此,如果您需要在中流评估变量或设置重定向,则可以。慢慢来。
echo "it takes time" |
{ exec 4>|file ; cat >&4 ; } |
( sleep 1 && cat <file )
it takes time
这是另一种方法:
echo "more of the same" |
( IFS= ; su -mc 'echo '"$(printf "'%s' " "`cat`")"' >|file' </dev/tty ) |
echo end of pipe
如果你不这样做,( subshell )
命令$(cat)
也会得到</dev/tty
。
但如果您使用here-doc,则不需要两个cat
s:
rm ./file
su -c 'cat <&3 >|./file; echo "middle here"' 3<<HERE >&2 | {\
until [ -s ./file ] ; do sleep 1 ; done ;\
sed 's/beginning/end/' ./file ; }
$(echo "this is the beginning" | sed 'a\of the pipeline' | tee /dev/stderr)
HERE
输出:
this is the beginning
of the pipeline
Password:
middle here
this is the end
of the pipeline
上面的大部分内容只是为了演示这一点。您真正需要的是:
su -c 'cat <&3 >./file' 3<<HERE | { wait as needed ; more stuff to do ; }
$(echo "something" | and other things)
HERE