Unix 是否有从 stdin 读取并写入文件的命令(例如 tee 而不将输出发送到 stdout)?

Unix 是否有从 stdin 读取并写入文件的命令(例如 tee 而不将输出发送到 stdout)?

我想将需要 root 才能读/写的文件从一个系统复制到另一个系统。我当前的解决方案是在每个系统上使用 sudo 并使用 tee,如图所示。

ssh host sudo cat /etc/somefile | sudo tee /etc/somefile > /dev/null

这是可行的,但是 tee 将其输入发送到 stdout,所以我必须将tee的输出发送到 /dev/null。

我查看了 UNIXcat和复制命令cp,但没有找到答案。
https://man7.org/linux/man-pages/man1/cp.1.html
https://man7.org/linux/man-pages/man1/cat.1.html


更新:我现在意识到我应该声明该解决方案需要支持,sudo因此简单的使用解决方案cat将不起作用。

例如,

ssh host sudo cat /etc/somefile | sudo cat > /etc/somefile

失败是因为该目录/etc只能由 root 写入(在我的例子中),并且文件的重定向> /etc/somefile在当前用户(无权写入 /etc 的权限)下运行。

答案1

有:

sh -c 'exec cat > file'

或者对于任意$files,作为环境变量传递:

sudo FILE="$file" sh -c 'exec cat > "$FILE"'

或者作为参数:

sudo sh -c 'exec cat > "$1"' sh "$file"

(其中sh进入,以及该内联脚本的$0内容)。$file$1

(另请参阅>>代替>打开于附加模式,或1<>在不截断的情况下打开(并在读+写模式下)以就地覆盖文件,类似于dd's conv=notrunc)。

无论如何,做不是做:

sudo sh -c“执行猫> $文件”

$file因为如果包含 shell 语法中的任何特殊字符(例如空格、、;... ) ,则会失败,$并引入命令注入漏洞。


还有:

dd bs=65536 of=file

(与status=noneGNU 实现dd或兼容来抑制传输报告。有更多选项来控制如何打开文件,其列表随实现而变化dd)。


在大多数系统上:

cp /dev/stdin file

还有的moreutils还有

sponge file

sort至少使用 GNU并且在文本输入上:

sort -mo file

使用文本输入(或sed可以处理非文本的实现):

sed -n 'w file'

使用文本输入:

awk '{print > "file"}'

或者使用 GNU awk

gawk -v ORS= '{print $0 RT > "file"}'

在这里,您还可以以root身份打开本地文件,然后ssh以普通用户身份运行:

sudo zsh -c '
  USERNAME=$SUDO_USER ssh host 'sudo cat /etc/somefile' > /etc/somefile'

这意味着数据不必通过额外的管道传输。

您还可以使用即时压缩xz并在本地端解压缩,pixz支持解压缩到文件中:

ssh host 'sudo xz -0 -c /etc/somefile' | sudo pixz -tdo /etc/somefile

答案2

如果有多个文件并且它们需要位于目标上的相同位置,tar则可以将文件复制到此处的不同目录,但管道也可能以ssh某种方式涉及。如果不适合您,可以p保留文件权限或一些压缩标志。ssh

$ mkdir output
$ echo foo > foo
$ echo bar > bar
$ tar cf - foo bar | ( cd output && tar xf - )
$ cat output/*
bar
foo

tar如果系统之间的实现不同,可能会出现可移植性问题。

答案3

cat是按照您的要求执行的最简单的程序。特别是cat -,它告诉命令从其标准输入读取数据。

sudo管道命令的左侧不清楚/etc/somefile.这是我对答案的最佳猜测:

sudo cat /etc/somefile | ssh me@otherhost 'sudo cat - > /etc/somefile'

相关内容