Как правильно экранировать символы для обратных кавычек для ssh в Perl? - PullRequest
3 голосов
/ 09 марта 2012

У меня есть этот код:

$script = "console.log(\"It works!\");";
$output = qx/ssh user@123.123.123.123 $script | interpreter/;

Предполагается запустить $script через интерпретатор и записать его в $output. Проблема в том, что это не работает. Как правильно выбрать персонажей?

Ответы [ 3 ]

4 голосов
/ 09 марта 2012

Подумайте о том, что вы пытаетесь сделать только с помощью ssh. Оба они выдают одинаковый результат, но работают по-разному:

ssh user@host 'echo "puts 2+2" | ruby'
echo "puts 2+2" | ssh user@host ruby

Во-первых, удаленная оболочка выполняет конвейер. (Если у вас нет этих одинарных кавычек, что происходит?) Во втором случае он передается через локальную оболочку к команде ssh и запускается интерпретатор.

Вместо того, чтобы совершать запутанные экранирование кода, чтобы он правильно выводился, когда втиснулся через sh, я предпочитаю передавать текст через stdin. Это просто проще.

Используя IPC :: Run , чтобы выполнить всю тяжелую работу:

#!/usr/bin/env perl

use strict;
use warnings;

use IPC::Run qw(run);

my $in = <<FFFF;
2 + 2
8 * (2 + 3)
FFFF

my $cmd = [qw(ssh user@host perl calc.pl)];

run $cmd, \$in, \my $out, \my $err or die "ssh: $?";

print "out: $out";
print "err: $err";

(calc.pl - простая программа-калькулятор инфиксов, которая у меня была)

Вот вывод, который я получаю:

out: 4
40
err: (SSH banners and pointless error messages)

Просмотр вызовов system или qx// в Perl-скрипте является признаком проблемы. В общем, мне не нравится думать о синтаксисе оболочки или цитировании оболочки, когда я не пишу shell; это не имеет ничего общего ни с проблемой, которую я пытаюсь решить, ни с инструментом, с которым я ее решаю. (И это игнорирует любые последствия для безопасности.)

О, и если вам не нужно смешивать со стандартным вводом, но вы все еще хотите выполнять и захватывать вывод из других программ, всегда есть IPC :: System :: Simple .

3 голосов
/ 09 марта 2012

Поскольку вы используете Perl, вы должны делать это на Perl, а не вызывать внешнюю команду.

Пробовали ли вы модуль Perl Net :: SSH :: Perl ?

Я бы также использовал qq вместо кавычек при установке значения $script.Использование qq удаляет весь как заключить в кавычки беспорядок.Любой символ, который появляется после qq, является вашим разделителем строк.Все они действительны:

my $string = qq/This is a "string" with a quote/;
my $string = qq|This is a "string" with a quote|;
my $string = qq*This is a "string" with a quote*;

Специальными операторами сопоставления котировок являются ( и ), [ и ], { и }:

my $string = qq(This (is (a "string" with) a) quote);

Обратите внимание, что я могу использовать скобки в качестве разделителей строк, даже если в моей строке есть скобки.Это нормально, если эти скобки сбалансированы.Это не сработает:

my $string qq(This is an "unbalanced" parentheses ) that breaks this statement);

Но тогда я могу переключиться на квадратные или фигурные скобки:

my $string qq[This is an "unbalanced" parentheses ) but still works.];

Вот версия вашей программы на Perl:

use strict;     #Always use!
use warnings;   #Always use!
use Net::SSH::Perl;

#
# Use Constants to set things that are ...well... constant
#
use constant {
   HOST => "123.123.123.123",
   USER => "user",
};

my $script = qq[console.log("It works!");];
my $connection = Net::SSH::Perl->new(HOST);
$connection->login(USER);
my ($output, $stderr, $exit_code) = $connection->cmd($script);
0 голосов
/ 09 марта 2012

использование Net :: OpenSSH :

my $ssh = Net::OpenSSH->new('user@123.123.123.123');
my $output = $ssh->capture({stdin_data => 'console.log("It works!");'},
                           'interpreter');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...