带有嵌套ls和head的ssh尾部无法访问

时间:2017-01-22 13:25:53

标签: linux shell ssh

我正在尝试执行以下命令:

$ ssh root@10.10.10.50 "tail -F -n 1  $(ls -t /var/log/alert_ARCDB.log | head -n1 )"

ls: cannot access /var/log/alert_ARCDB.log: No such file or directory
tail: cannot follow `-' by name

当我分别登录ssh然后执行

时,请注意返回的错误
tail -F -n 1  $(ls -t /var/log/alert_ARCDB.log | head -n1 )"

见下文:

# ls -t /var/log/alert_ARCDB.log | head -n1 
/var/log/alert_ARCDB.log

为什么会发生这种情况以及如何解决它。我试图在一行中这样做,因为我不想创建一个脚本文件。

非常感谢

2 个答案:

答案 0 :(得分:0)

在执行命令之前,发生了Shell参数扩展。

这是一个简单的例子。如果我打字......

ls "$HOME"

... shell首先将$HOME替换为我的主目录的路径,然后运行类似ls /home/larsks的内容。 ls命令不知道命令行最初有$HOME

如果我们看看你的命令......

$ ssh root@10.10.10.50 "tail -F -n 1  $(ls -t /var/log/alert_ARCDB.log | head -n1 )"

......我们看到你处于完全相同的情况。在执行 $(ls -t ...)之前,ssh表达式已展开。换句话说,该命令正在运行本地系统。

您可以使用单引号禁止本地系统上的shell扩展。例如,运行:

echo '$HOME'

将产生:

$HOME

所以你可以跑:

ssh root@10.10.10.50 'tail -F -n 1  $(ls -t /var/log/alert_ARCDB.log | head -n1 )'

但这里还有另一个问题。如果/var/log/alert_ARCDB.log文件,那么您的命令没有任何意义:在单个文件上调用ls -t无法获取任何内容。

如果alert-ARCDB.log目录,则会遇到其他问题。 ls /some/directory的结果是没有任何目录前缀的文件名列表。如果我运行类似的东西:

ls -t /tmp

我会得到像

这样的输出
file1
file2

如果我这样做:

tail $(ls -t /tmp | head -1)

我最终得到的命令如下:

tail file1

这会失败,因为我的当前目录中没有file1

答案 1 :(得分:0)

一种方法是将要执行的命令传递给ssh。实现这一目标的一种简单方法是首先创建一个将回显您想要执行的命令的函数:

remote_commands()
{
  echo 'cd /var/log/alert_ARCDB.log'
  echo 'tail -F -n 1  "$(ls -t | head -n1 )"'
}

cd将允许您使用ls列出的相对路径。单引号确保所有内容都按原样发送到远程shell,不会发生本地扩展。

然后你可以做

ssh root@10.10.10.50 bash < <(remote_commands)

这假设alert_ARCDB.log是一个目录(否则我不确定为什么你想在之后添加head -n1。)