Como executar o perl one-liner do script perl (apropriadamente com escape)

1

Eu tenho um script perl dentro do qual eu preciso executar um simples perl one-liner em um host remoto:

ssh 192.168.1.1 "perl -pi.bup -e 's/^(\s+?kernel)(.*)(?<!audit=1)$/$1$2 audit=1/' /etc/grub.conf"

Isso simplesmente adiciona " audit=1 " ao final de cada linha do kernel em /etc/grub.conf , se ainda não existir.

O one-liner funciona muito bem quando executado diretamente no host, mas não quando executado via ssh dentro de outro script perl. Eu tentei escapar de todos os sinais de dólar com uma ou mais barras invertidas e também tentei escapar da barra invertida em " \s ", mas nada que eu faça parece funcionar.

Note que não quero copiar um script para o host remoto e depois executá-lo - eu gostaria de fazê-lo usando o comando ssh diretamente.

Como escapar disso corretamente para que funcione?

- Atualização 9/9/2015 para mostrar exatamente o que estou fazendo no script perl:

sub SomeMethod
{
   &RunCommand($host, "perl -pi.bup -e \'s/^(\s+?kernel)(.*)(?<!audit=1)\$/\\ audit=1/\' /etc/grub.conf");
}

sub RunCommand
{
    my ($server, $command) = @_;
    my $commandOutput = "";

    if ($server ne "")
    {
        $command = "ssh $server \"$command\"";
    }

    $commandOutput = '$command'; 
    print $commandOutput;

    if (($? >> 8) != 0)
    {
        &LogMessage ("$command failed:\n\n$commandOutput");
        return $commandOutput;
    }
    return $commandOutput;
}

- Atualização # 2, usando system em vez de back-ticks:

system 'ssh', $host, 'perl', '-pi.bup', '-e', 's/^(\s+?kernel)(.*)(?<!audit=1)$/$1$2 audit=1/', '/etc/grub.conf';
bash: -c: line 0: syntax error near unexpected token '('
bash: -c: line 0: 'perl -pi.bup -e s/^(\s+?kernel)(.*)(?<!audit=1)$/$1$2 audit=1/ /etc/grub.conf'

Ok, eu posso usar o sistema aqui, mas como escapar corretamente ??

    
por Zek 09.09.2015 / 22:41

3 respostas

2

Como você está editando o arquivo remoto no lugar, não é necessário capturar a saída, portanto system seria preferível ao uso de backticks:

system 'ssh', '192.168.1.1', 'perl', '-pi.bup', '-e', 's/^(\s+?kernel)(.*)(?<!audit=1)$/$1$2 audit=1/', '/etc/grub.conf';

Note que você não precisa passar o comando remoto como um único parâmetro para o ssh. Isso ajuda a citar um pouco. Se você realmente quiser, você pode:

system 'ssh', '192.168.1.1', q{perl -pi.bup -e 's/^(\s+?kernel)(.*)(?<!audit=1)$/$1$2 audit=1/' /etc/grub.conf};

Usando o operador q{} para permitir que o perl one-liner use aspas simples.

Eu faria isso, na verdade:

use Try::Tiny;
use IPC::System::Simple qw{capture};

sub SomeMethod
{
    my $output = RemoteCommand(
                    $host, 
                    q{perl -pi.bup -e 's/^(\s+?kernel)(.*)(?<!audit=1)$/$1$2 audit=1/' /etc/grub.conf}
                );
}

sub RemoteCommand
{
    my ($server, $command) = @_;
    my $output;

    try {
        $output = capture('ssh', $server, $command);
    }
    catch {
        LogMessage("command failed: ($command) : $_");
        $output = $_;
    };

    return $output;
}
    
por 09.09.2015 / 23:35
0

Eu finalmente consegui trabalhar.

Do bash diretamente:

echo 's/^(\s+?kernel)(.*)(?<!audit=1)$/$1$2 audit=1/' | ssh 192.168.1.1 "perl -pi.bup - /etc/grub.conf"

Do script perl:

my $command = "echo 's/^(\s+?kernel)(.*)(?<!audit=1)\$/\\ audit=1/' | ssh $_wsAddress 'perl -pi.bup - /etc/grub.conf' ";
&RunCommand("", $command);
    
por 10.09.2015 / 01:17
0

Eu tentei com o seguinte comando simples e funciona

ssh localhost "sed -i.bck '/[^audit]/{s/\(^\s\+kernel.*\)/ audit=1/g}' /boot/grub/menu.lst"

Não é sobre sed vs perl , mas usar o comando anterior é mais claro para arquivar o que você deseja.

    
por 09.09.2015 / 23:58