如何从 perl 脚本执行 perl 单行代码(正确转义)

如何从 perl 脚本执行 perl 单行代码(正确转义)

我有一个 perl 脚本,我需要在远程主机上执行一个简单的 perl 单行命令:

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

如果不存在“ ”,则只需将“ audit=1”添加到每个内核行的末尾即可。/etc/grub.conf

单行代码在主机上直接运行时工作正常,但在另一个 perl 脚本中通过 ssh 执行时则不行。我尝试用一​​个或多个反斜杠转义所有美元符号,也尝试转义“ \s”中的反斜杠,但似乎都不起作用。

注意,我不想将脚本复制到远程主机然后执行它 - 我想直接使用 ssh 命令来执行此操作。

如何正确摆脱这种情况以使其发挥作用?

-- 2015 年 9 月 9 日更新,以准确显示我在 perl 脚本中所做的事情:

sub SomeMethod
{
   &RunCommand($host, "perl -pi.bup -e \'s/^(\s+?kernel)(.*)(?<!audit=1)\$/\$1\$2 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;
}

-- 更新 #2,使用system而不是反引号:

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'

好的,我可以在这里使用系统,但是如何正确地退出它呢?

答案1

由于您正在编辑远程文件,因此不需要捕获输出,因此system比使用反引号更可取:

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

请注意,您不必将远程命令作为单个参数传递给 ssh。这对引用有点帮助。如果您确实想要,您可以:

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

使用q{}运算符允许 perl 单行命令使用单引号。


事实上我会这么做:

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;
}

答案2

我终于让它工作了。

直接从 bash:

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

来自 perl 脚本:

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

答案3

我尝试了以下简单命令,它有效

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

不是关于sed vs perl,但使用前面的命令可以更清楚地存档您想要的内容。

相关内容