我有一个 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
,但使用前面的命令可以更清楚地存档您想要的内容。