如何用GNU Parallel+SSH单命令完成批量远程主机的文件传输、执行与结果获取?
如何用GNU Parallel+SSH单命令完成批量远程主机的文件传输、执行与结果获取?
我完全懂你的需求——不想分开跑两次Parallel(一次传文件、一次执行脚本),就想用一条命令搞定批量远程主机的脚本传输、执行和结果返回。你当前遇到的远程文件为空的问题,其实是stdin在Parallel和SSH的交互中没被正确分发导致的,咱们来一步步解决:
先说说你原来的命令为啥失效
你写的命令里,< file_for_send.sh是把本地脚本内容传给整个Parallel进程的stdin,但Parallel在同时启动多个SSH会话时,没办法把这一份stdin内容分发给每个独立的SSH进程,所以远程主机上的cat > file_for_send.sh根本没收到任何输入,自然文件是空的。
方案1:直接传脚本内容执行(无需在远程保存文件)
如果你的需求只是执行脚本并获取结果,不需要在远程主机上保留脚本文件,那这个方案最简单——直接把脚本内容通过SSH的stdin传给远程的bash执行:
parallel --tagstring {} -j 25 -q -a file_ip_addr_hosts.csv \ sshpass -p pass ssh user@{} 'bash -s' < file_for_send.sh
解释一下:
bash -s让远程的bash从stdin读取命令/脚本内容,这样本地的脚本直接通过SSH管道传递过去执行,结果会实时返回给Parallel,还省了在远程创建文件的步骤。- 这个方式完全不需要额外的文件传输操作,一条命令搞定所有。
方案2:必须在远程保存脚本?用Parallel自带的文件传输功能
如果你需要在远程主机上保留脚本文件,那别自己写scp逻辑了,GNU Parallel本身就带了文件传输的功能,用--put选项就能自动把本地文件传到每个远程主机:
parallel --tagstring {} -j 25 -a file_ip_addr_hosts.csv \ --put file_for_send.sh \ sshpass -p pass ssh user@{} 'source ./file_for_send.sh && echo result'
解释一下:
--put file_for_send.sh告诉Parallel:在执行每个远程SSH命令之前,先把本地的file_for_send.sh传到对应远程主机的当前工作目录(默认是用户的home目录)。- 之后你在SSH命令里直接引用这个脚本路径就行,Parallel已经帮你搞定了传输的细节,不用再手动处理scp和SSH的合并。
额外提醒:尽量避免明文密码
虽然你用了sshpass,但命令行里明文写密码其实不太安全,建议尽量配置SSH密钥登录,这样既安全又不用每次输密码(也不用写sshpass了)。
备注:内容来源于stack exchange,提问作者Дмитрий Брыкалов
相关产品推荐
相关产品推荐

