我可以将数据从一个命令传输到另一个命令,例如:
$ echo test | cat
test
不确定该打电话给什么我可以使用以下操作获得类似的效果:
$ cat < <(echo test)
test
<(echo test)
即时创建文件有什么害羞的地方。使用常规文件,它看起来像:
$ cat file
test
$ cat < file
test
这与 ssh 一样有效:
$ ssh server cat < <(echo test)
test
使用 ssh-example 作为基础,人们可能会认为你可以这样做:
$ pdsh -a cat < <(echo test)
但没有数据发送到连接的计算机上的 cat,并且命令永远不会终止。
tee
似乎能够将标准输入上收到的内容发送到多个地方:
$ tee >(cat) >(cat) < <(echo test)
test
test
test
有可能实现同样的目标pdsh
吗?
答案1
由于pdsh
不支持 stdin 转发/广播,您可以考虑clush
使用ClusterShell项目作为 的直接替代品pdsh
,它支持 stdin 广播:
$ clush -a cat < <(echo test)
n1c01: test
n2c01: test
n1c02: test
n2c02: test
此外,clush
具有良好的输出收集功能(例如不需要外部管道dshback
),如下所示:
$ clush -ab cat < <(echo test)
---------------
n[1-2]c[01-02] (4)
---------------
test
答案2
您需要引用远程命令,以便整个命令在远程主机上运行。例如
pdsh -a 'cat < <(echo test)'
如果没有引号,仅有的cat
在远程主机上运行。重定向 ( <
) 和流程替代 <(echo test)
在本地主机上运行。
当只有一台远程主机消耗 的输出echo test
(例如使用命令ssh
)时,这可以工作......但是当有多个远程主机想要消耗该输出时(例如因为您使用pdsh
而不是ssh
),它就不起作用。
答案3
我与其中一位开发人员取得了联系pdsh
并了解了以下内容:
您想要的是“stdin 广播”,不幸的是 pdsh 从未添加对此的支持。这将是一个很好的功能,但历史上并没有太大的需求,所以它从未被完成。
这似乎证实了这篇文章中已经确定的内容。
然而,紧随其后的是:
顺便说一句,事实并非如此不可能的进行标准输入广播。作为 HPC 调度程序一部分的并行启动器可以做到这一点,例如 srun(1) 等。该机制是 stdin 被读入一次,然后复制到每个远程进程的缓冲区,即复制是在并行启动器内部完成的。
跟进的原因是有一些误导性的答案那个 stackexchange 帖子。
解决串行 for 循环问题的另一种方法是从 GNU Parallel 或 pdsh -R exec 运行 ssh。 pdsh -R exec 的示例:
$ pdsh -R exec -w 主机[0-10] bash -c 'ssh %h cat < <(回显测试)'
当然,这里的缺点是您要创建 N 次用于重定向的临时文件。可能更好的方法是将输出放入本地文件中,然后将该文件添加到每个 ssh 命令中。
pdsh/parallel 相对于 for 循环的好处是可以获得并行性。
在我自己的测试中,我在使该示例正常工作时遇到了一些麻烦:
root@master# pdsh -R exec -w host1 bash -c 'ssh %h cat < <(echo test)'
host1: bash: -c: line 0: syntax error near unexpected token `<'
host1: bash: -c: line 0: `ssh n1 cat < <(echo test)'
pdsh@master: host1: bash exited with exit code 1
一个小的调整让它活跃起来,那就是使用“正常”文件:
root@master# cat data.txt
test from file
root@master# pdsh -R exec -w host1 bash -c 'ssh %h cat < data.txt'
host1: test from file
结论:pdsh
可以开发一个功能来更好地处理我的要求,但即使是现在,也有方法可以实现我的要求。
答案4
我认为您希望将数据发送到多台计算机的原因是您无法轻松地将其放入临时文件并将文件传输到远程计算机。也许输出是连续生成的,也许它太大而无法放入磁盘。
GNU Parallel--tee
可以帮助您:
seq 1000 |
parallel --tee --pipe ssh {} wc ::: server1 server2
将seq 1000
和替换wc
为您的命令。
在未经修改的 GNU/Linux 系统上,它应该能够在 250 台服务器上运行。如果您需要更多,您将用完文件句柄,并且必须更改ulimit -n
or nofile
in /etc/security/limits.conf
or /proc/sys/fs/file-max
。
在幕后启动了以下内容(这有点复杂,因为 GNU Parallel 从命令中收集 stdout 和 stderr,但原理是相同的):
... | tee >(ssh server1 wc) >(ssh server2 wc) >/dev/null
所以性能与tee
.但这也意味着ssh
所有服务器都将是并行的——而不是一次只有几个。