我想将需要 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'
或者对于任意$file
s,作为环境变量传递:
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=none
GNU 实现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'