我必须通过 ssh 登录远程服务器并转到 tmp 文件夹,然后必须运行 rm 命令。但是当我执行下面的脚本时,它会转到远程服务器,但不会转到临时文件夹,也不运行 rm 命令。
#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS
答案1
您的代码唯一真正的问题是您的循环缺少do
and done
,这会给您带来语法错误,并且您正在使用它i
作为循环变量,但尝试连接一些server
很可能未设置的变量。
除此之外,您正在使用cat
不带引号的命令替换,即一般来说如果您不确定您将读取没有空格和文件名通配符的字符串,那么这是一个坏主意(尽管大多数主机的名称在这方面表现良好)。
大多数情况下,逐行读取输入会更好,如下所示:
while IFS= read -r remote; do
ssh -n "$remote" 'rm -f /tmp/log52.log'
done <list
我ssh -n
在这里使用它来停止ssh
读取其标准输入流(它将连接到文件list
)。如果没有-n
,ssh
将读取 的剩余内容list
,并且您的循环将仅运行一次迭代。
或者,如果您确实想从此处文档中读取命令:
while IFS= read -r remote; do
ssh -T "$remote" <<'END'
rm -f /tmp/log52.log
END
done <list
在这里,我使用ssh -T
显式禁用伪终端分配,这是不需要的,因为我们不做任何需要用户交互的事情。我这样做是因为ssh
会注意到它的标准输入流有数据,所以它会警告我们远程系统上没有可用的终端来进行交互。我们不需要-n
这里,因为我们正在从此处文档ssh
重新分配标准输入流。ssh
但循环可以用单个命令代替
xargs -I {} ssh {} 'rm -f /tmp/log52.log' <list
...xargs
实用程序将在其中读取线从文件中list
,将命令替换{}
为ssh
从文件中读取的行,并执行访问远程系统以删除特定文件的操作。rm -f
如果没有要删除的文件,我通常不会导致错误。
的一些实现xargs
允许与例如并行执行实用程序-P 4
(最多ssh
同时执行四个并发命令)。
答案2
#! /bin/bash
for i in `cat list`
do
echo $i
echo "-------------------------"
ssh $i "rm /tmp/log52.log"
done
如果您只需要删除单个文件,您可能只想在一行中简单地指定它。此外,您可能会发现添加-f
到rm
.
答案3
您不能像这样简单地重定向 ssh 会话的标准输入。您应该看到类似以下的错误消息:
伪终端不会被分配,因为 stdin 不是终端
您需要使用 ssh 选项 -tt 来强制分配伪设备。尝试这个:
#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh -tt $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS