linux 运行相对复杂的查找|xargs命令从远程服务器

643ylb08  于 2022-11-02  发布在  Linux
关注(0)|答案(2)|浏览(124)

我有一个命令,我可以在Linux服务器上运行它而不会出现任何问题(让我们称之为server 1)。
在这里

myuser@server1:  find -L /data* -type d -maxdepth 2 | xargs -d $'\n' sh -c 'for arg do echo "$arg" $(stat -f -L -c %T  "$arg") ; done'

这将列出server 1目录树中两级以下的所有目录,并显示每个目录的关联文件系统。
现在,我想做的是在对server 1执行ssh-ing之后,从驻留在远程服务器(我们称之为server 2)上的bash脚本中运行完全相同的命令,但要将输出写入server 2上的文件。

myuser@server2: ssh "myuser@server1"  "find -L /data* -type d -maxdepth 2 | xargs -d $'\n' sh -c 'for arg do echo "$arg" $(stat -f -L -c %T  "$arg") ; done'" >output.txt

但是我似乎找不到正确的语法。我认为上面的命令做变量扩展不正确。你能帮忙吗?
谢谢你-格里戈

xlpyo6sf

xlpyo6sf1#

不使用xargs和pipe,而是重新排列命令:

ssh myuser@server1 \
'for d in $(find -L ~/data* -type d -maxdepth 2); do echo "$d $(stat -f -L -c %T $d)"; done'
g6ll5ycj

g6ll5ycj2#

您作为远程命令给予给ssh的字符串在被发送到远程机器进行解析和执行之前,需要在本地机器上进行正常的解析。


# prints the numbers 1 2 3

for arg in 1 2 3 ; do echo $arg ; done

# prints three empty lines, assuming $arg is unset in your local environment

ssh user@remotehost "for arg in 1 2 3 ; do echo $arg ; done"

在第二个示例中,当bash对命令行求值时,它在运行ssh之前,按照常规的参数扩展规则用$arg替换其值。这意味着实际发送到远程计算机的命令是for arg in 1 2 3 ; do echo ; done
有很多很好的建议可以解决BashFAQ上的这个问题。
1.手动重新引用。在我的简单示例中,可以使用单引号而不是双引号来保护字符串不被求值。由于嵌入了单引号,代码稍微复杂一些,因此必须通过将每个单引号替换为'\''来处理转义。
1.使用stdin而不是命令行。例如,heredoc可以让你将命令传递到远程机器,而不需要太多的手动格式化。
1.如果远程shell是Bash,则使用printf %q之类的工具。这将格式化一个字符串,使其可以像ssh那样安全地计算两次。

相关问题