更新

更新

我正在尝试让这个脚本工作(它应该做的是在远程服务器的最后一个日志文件中搜索字符串):

ssh -i $ssh_key_file ubuntu@$1 -t "cd /path/to/logs; grep \"POST api/orders \" `ls -Art | grep info | tail -n 1` -A 2 | grep \"'store_id' => '$2'\" -B 1; bash --login"

这个脚本

`ls -Art | grep info | tail -n 1`

应该返回给我最后一个日志文件,如果我在远程服务器上单独运行该脚本,这就是它的一个例子:

$ ls -Art | grep info | tail -n 1
info-2019-04-10.log

此外,如果我通过对日志文件名进行硬编码来运行与上面完全相同的脚本,那么它就可以正常工作:

 ssh -i $ssh_key_file ubuntu@$1 -t "cd /path/to/logs; grep \"POST api/orders \" info-2019-04-10.log -A 2 | grep \"'store_id' => '$2'\" -B 1; bash --login"

我能够将此(查找最后一个日志文件)脚本嵌入到其他 shell 脚本中,并且它运行良好,如下所示:

ssh -i $ssh_key_file ubuntu@$1 -t "cd /path/to/logs; grep $2 `ls -Art | grep info | tail -n 1`; bash --login"

我在原始脚本中做错了什么?

更新

使用此脚本

function totCreateOrder()
{
ssh -i "$ssh_key_file" ubuntu@"$1" -t<<EOF
cd /var/www/toters/storage/logs && grep "POST api/orders " "\$(ls -Art | grep info | tail -n 1)" -A 2 \
| grep "'store_id' => '"'$2'"'" -B 1
bash --login
EOF
}

返回这个奇怪的错误消息

totCreateOrder $prod1as 1006
Pseudo-terminal will not be allocated because stdin is not a terminal.
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1067-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

74 packages can be updated.
0 updates are security updates.

New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


*** System restart required ***

抬头望去这个错误意味着什么,然后做了这个

function totCreateOrder()
{
ssh -i $ssh_key_file ubuntu@$1 -t -t<<EOF
cd /var/www/toters/storage/logs && grep "POST api/orders " "\$(ls -Art | grep info | tail -n 1)" -A 2 \
| grep "'store_id' => '"'$2'"'" -B 1
EOF
}

但后来我收到这个错误信息:

totCreateOrder $prod1as 1006
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1067-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

74 packages can be updated.
0 updates are security updates.

New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


*** System restart required ***
Last login: Thu Apr 11 03:38:32 2019 from 185.81.141.32
 1"$(ls -Art | grep info | tail -n 1)" -A 2 | grep "'store_id' => '"'1006'"'" -B

更新二

我逐行检查了脚本...它确实起到了作用,因为它实现了以下效果:

  • 登录到远程服务器
  • 能够ls -Art | grep info | tail -n 1正确解析
  • 在远程服务器上运行此命令:grep "POST api/orders " "$(ls -Art | grep info | tail -n 1)" -A 2

    函数测试(){ ssh -i $ssh_key_file ubuntu@$1 -t -t<

它返回了这个

test $prod1as
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1067-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

74 packages can be updated.
0 updates are security updates.

New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


*** System restart required ***
Last login: Thu Apr 11 05:18:10 2019 from 185.81.141.85
ubuntu@ip-x-xx-xx:~$ cd /var/www/toters/storage/logs
-Art | grep info | tail -n 1)" -A 2 storage/logs$ grep "POST api/orders " "$(ls
[2019-04-11 04:10:39] production.INFO: POST api/orders [] []
[2019-04-11 04:10:39] production.INFO: array (   'store_id' => '831',   'items' =>    array (     0 =>      array (       'additional_info' => '',       'addons' =>        array (       ),       'quantity' => 1,       'id' => 129369,
),     1 =>      array (       'additional_info' => '',       'addons' =>        array (       ),       'quantity' => 1,       'id' => 133351,     ),     2 =>      array (       'additional_info' => '',       'addons' =>        ..

然而当我像这样添加管道时,事情就发生了变化:

function test()
{
ssh -i $ssh_key_file ubuntu@$1 -t -t<<EOF
cd /var/www/toters/storage/logs 
grep "POST api/orders " "\$(ls -Art | grep info | tail -n 1)" -A 2 | grep "'store_id' => '"'$2'"'" -B 1
EOF
}

它返回这个

 $ test $prod1as 1006
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1067-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

74 packages can be updated.
0 updates are security updates.

New release '18.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


*** System restart required ***
Last login: Thu Apr 11 05:33:22 2019 from 185.81.141.85
ubuntu@ip-10-0-1-39:~$ cd /var/www/toters/storage/logs
-Art | grep info | tail -n 1)" -A 2 | grep "'store_id' => '"'1006'"'" -B 1"$(ls

答案1

我在原始脚本中做错了什么?

主要问题是:双引号中的反引号在本地扩展。通常我会推荐 here document,但对于你的情况,你需要一个伪终端,并且无法真正重定向标准输入(这是 here document 所做的)。无论如何,使用$()而不是反引号并转义$(或者你可以坚持使用反引号并转义它们,但$()总体而言) 或用单引号括住此片段。这应将整个$( … )语法传递到远程端。您还应确保远程 shell 将其放在双引号中,因为很明显,在这种情况下您不希望结果经过分词和模式匹配。

一般来说不应该解析ls。我猜很难用更强大的代码替换您的代码,除非find远程端支持-printf。但我不知道它是否支持,所以我不会改进这部分。(除了这个:为什么要反转输出ls并取最后一个条目?为什么不从非反转输出中取第一个条目?您grep支持吗-m 1?)

grep如果失败则不应调用cd

您应该对变量使用双引号,除非您知道不需要这样做。:) 不引用$ssh_key_file可能$1会打开一个罐头……惊喜.$2在您的代码中有些不同。从上下文来看,它应该在本地扩展,并将结果传递给远程 shell。无论到达远程 shell 的是什么,解析。我猜你不希望本地扩展的结果$2在远程端进行变量扩展(或者你想?)。在你的原始脚本中,远程 shell 会看到$2在双引号内的单引号中本地扩展的外在的东西很重要。因此,您应该让本地扩展的$2字符串在单引号中出现在远程 shell 中。但是,如果您将此字符串嵌入为模式的一部分grep,则应该将它们用双引号引起来。这会导致引用混乱,这很棘手。

你传递给远程 shell 的仍然是一个字符串,它将是解析,(本地)的某些值$2将破坏代码。代码注入是可能的。这是一个常见问题,其中依赖于变量的命令作为要解析的字符串传递,这很难清理。我希望你能完全控制本地$2。如果没有,这是一个漏洞:任何控制它的人都可以以远程主机上的用户身份运行任意命令。例如,如果在扩展为(双引号属于此处的变量)ubuntu时运行原始代码,你会感到不愉快的惊讶(所以不要这样做)。$2"& rm -rf ~/ & "

以下代码片段完全未经测试。您的代码看起来非常具体,因此很难测试。

ssh -i "$ssh_key_file" ubuntu@"$1" -t "
cd /path/to/logs && grep \"POST api/orders \" \"\$(ls -Art | grep info | tail -n 1)\" -A 2 \
| grep \"'store_id' => '\"'$2'\"'\" -B 1
bash --login
"

笔记:

  • 由于本地扩展$2和单引号需要到达远程端,我决定将整个命令用双引号引起来。将部分命令放在单引号中可能会减少引用(和转义)的混乱,但这不一定会使命令变得不那么神秘,因为很难发现哪部分是以何种方式引用的。
  • $2仍然可以进行代码注入。

录取后通知

OP 报告以下代码有效:

function test()
{
ssh -i "$ssh_key_file" ubuntu@"$1" -t "cd /path/to/logs; grep \"POST api/orders \" \"\$(ls -Art | grep info | tail -n 1)\" -A 2 \
    | grep \"'store_id' => '\"'$2'\"'\" -B 1 \
    ; bash --login"
}

此代码以与上述代码相同的方式修复了主要问题。变化可能在语法方面很重要(?),但我认为它们对于主要问题来说是次要的。

相关内容