【问题标题】:remove files via ssh and xargs通过 ssh 和 xargs 删除文件
【发布时间】:2019-10-28 20:23:40
【问题描述】:

我正在尝试使用 find 和 xargs 通过 ssh 删除文件。在本地机器命令正常工作。我也在使用例外列表。

我曾尝试更改 ' ' 和 " " 之间的括号,但它不起作用。

save_files=(test1 test2)

在本地机器上:

find / -mindepth 1 | grep -vE "$(IFS=\| && echo "${save_files[*]}")" | xargs rm -rf

通过 ssh:

su - user -c "ssh host find / -mindepth 1 | grep -vE '$(IFS=\| && echo "${save_files[*]}")' | xargs rm -rf"

在上面的 ssh 命令中,xargs 正在本地执行。我需要远程机器上的 xargs 。即使我把 find 命令放在 '' 括号中,如下所示:

su - user -c "ssh host 'find / -mindepth 1 | grep -vE '$(IFS=\| && echo "${save_files[*]}")' | xargs rm -rf'"

【问题讨论】:

  • 附带说明,删除“/”下与动态模式不匹配的任何内容是一项冒险操作。如果模式中存在问题,则可能会删除太多文件
  • '/' 只是这里的例子,在我的情况下,我使用其他目录。

标签: linux bash ssh xargs


【解决方案1】:

开始另一个答案,再次尝试单行,避免中间脚本。

关键问题是三级引用,而 shell 只支持两级引用(双引号、单引号)。我相信可以通过在模式中使用反引号来消除对第三级引用的需要,从而消除将其放入引号中的需要。

IFS=\| P="${save_files[*]}"   su - owner -c "ssh localhost 'set -vx ; find /tmp/xyz -mindepth 1 | grep -vE ${P//|/\\|} | xargs rm -rf'"

解决方案使用“转义”创建模式 - 参见“($P/|/\|}”,无需引用模式。如果 save_files 没有魔术字符,则应该可以工作。

注意事项:

  1. 请注意,我已将 '/' 替换为 /tmp/xyz,以减少意外复制/粘贴会删除重要数据的更改(我的 VM 上已经发生 :-( )。
  2. “set -vx”用于调试和故障排除,可以删除

【讨论】:

  • 似乎有效!我必须用我的案例对其进行更深入的测试,但命令通常可以正常工作。非常感谢!我会在做一些测试后回来。
  • 几乎可以正常工作,但如果 save_files 包含超过 2 个文件,其余文件就有问题。前有遗漏\ | + save_files=(test1 test2 test.ini test4) + IFS='|' + P='test1|test2|sapftp.ini|test4' + su - user -c 'ssh host '\''find /tmp/xyz -mindepth 1 -maxdepth 1| grep -vE test1\|test2|test.ini|test4 | xargs ls -l'\''' test4:找不到命令。 test.ini:找不到命令。
  • @mac 感谢您指出这一点。使用 ${P/|//\\|} (double //) 修改脚本以根据需要处理尽可能多的参数
  • 使用 (double //) 它仍然只影响第一个管道: su - user -c "ssh host 'find /tmp/xyz -mindepth 1 -maxdepth 1| grep -vE ${P/| //\\|} | xargs ls -l'" 错误与之前相同 - for 3th nad 4th filenames command not found.
  • @mac 糟糕,我把“双 /”放在了错误的位置。应该是 ${P//.../...} ,而不是 ${P/...//...}
【解决方案2】:

在远程主机上执行命令的代码:

su - user -c "ssh host 'find / -mindepth 1 | grep -vE '$(IFS=\| && echo "${save_files[*]}")' | xargs rm -rf'"

使用双引号将命令传递给'su -c',然后使用单引号将命令传递给'ssh'(其中包含双引号)。但是,引用不支持嵌套,因此 '$(IFS=... ... )' 中的引用实际上终止了 'find' 中的引用。

您可以使用“set -vx”前缀执行相同的操作,以查看扩展

su - owner -c "set -vx ; ssh localhost ...

你会看到

++ IFS='|'
++ echo 'test1|test2'
+ su - owner -c 'set -vx ; ssh localhost '\''set -x ; find /foo -mindepth 1 | grep -vE '\''test1|test2'\'' | xargs rm -rf'\'''
Password: 
+ ssh localhost 'set -x ; find /foo -mindepth 1 | grep -vE test1'
+ 'test2 | xargs rm -rf'
-su: test2 | xargs rm -rf: command not found
+ find /foo -mindepth 1
+ grep -vE test1
find: ‘/foo’: No such file or directory

建议的解决方案:

我无法找到获得三级引用的方法(非常令人沮丧)可能的解决方案可能是创建一个辅助脚本 h.sh,它将执行“ssh”命令,然后使用“调用”辅助脚本su - 用户'/path/to/helper.sh'

【讨论】:

  • 感谢您的回复!我正在尝试将此脚本构建为一个文件,因此我仍在寻找此命令或任何其他允许删除异常文件的解决方案。
  • @mac 我已经发布了一个针对单行的新答案。你可以试试,让我知道吗?
【解决方案3】:

你可以试试这个吗?

su - user -c "ssh host 'save_files=test; find / -mindepth 1 | grep -vE "$save_files" | xargs rm -rf'"

或者在切换为root用户之后尝试以下一个?

ssh host 'save_files=test; find / -mindepth 1 | grep -vE "$save_files" | xargs rm -rf'

【讨论】:

  • 第一个:save_files=test:找不到命令 查找几乎没问题,但有例外,应该跳过。第二个不适合我的情况。我必须先切换用户,然后再使用 ssh。顺便提一句。我发现在我的命令中,问题出在“su - user -c”上,因为没有它也可以工作。使用 'su - user -c' xargs 正在删除未找到的文件,而是删除本地计算机上当前目录中的文件。
  • 如果您可以作为 cronjob 执行,那么您可以通过在 bash 脚本中使用 ssh 命令设置 cronjob 来摆脱 su 选项。
  • 它通常是 bash 脚本的一部分,但脚本以 root 用户身份运行。远程主机连接仅适用于“用户”,这就是为什么我必须从根用户通过“su”进行切换。
  • 您是否尝试过使用 ssh -i 选项? ssh -i /home/user/.ssh/id_rsa.pub user@x.x.x.x
  • 使用 ssh -i 它询问密钥的密码,所以在我的情况下是不正确的。我必须不用密码登录。我也尝试过 find 和 xargs rm 之类的:su - user -c "ssh host cd directory;rm !(test)" 但它返回 "badly placed ()'s。
【解决方案4】:

首先连接你的远程系统并运行你需要的 bash 命令,比如 find 和 xargs

ssh root@MachineB 'bash command'

【讨论】:

  • 我需要以这种方式使用它:su - user -c "ssh..." 因为我以 root 用户身份执行此操作并且不想输入密码(用户具有远程主机的 ssh 密钥)
猜你喜欢
  • 2012-03-07
  • 1970-01-01
  • 2013-08-20
  • 2012-11-25
  • 2017-08-07
  • 2016-05-08
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多