我得到了这个在远程服务器上完美运行的命令
perl -ne 'print "$1,$2,$3\n" if /^[^\[]*\[\K([^]]+)[^{]*{[^[]*\["\K([^"]+)(?:(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/' /path/to/file.log
但当我尝试通过将其保存为shell 函数像这样:
function getRemoteLogs()
{
ssh -i $ssh_key_file ubuntu@$1 -t 'perl -ne `print "$1,$2,$3\n" if /^[^\[]*\[\K([^]]+)[^{]*{[^[]*\["\K([^"]+)(?:(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/` /path/to/file.log' > local.txt
}
$1
远程服务器的 IP 在哪里
它返回此错误:
bash: command substitution: line 0: syntax error near unexpected token `('
bash: command substitution: line 0: `print "$1,$2,$3\n" if /^[^\[]*\[\K([^]]+)[^{]*{[^[]*\["\K([^"]+)(?:(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/'
Unknown regexp modifier "/w" at -e line 1, at end of line
Unknown regexp modifier "/w" at -e line 1, at end of line
Unknown regexp modifier "/w" at -e line 1, at end of line
syntax error at -e line 1, near "18.log
"
Execution of -e aborted due to compilation errors.
我该怎么做呢?
答案1
您使用的反引号告诉 Perl 将其内部的所有内容作为命令传递到底层 shell - 就像 exec 或 system() 所做的那样。 这里'讨论 Perl 中的反引号的链接。
您确实需要引用远程服务器的整个 perl 命令,但您必须使用双引号。然后您必须转义内部双引号和否则会扩展的变量。
尝试一下:
ssh -i $ssh_key_file ubuntu@<remote ip> "perl -ne 'print \"\$1,\$2,\$3\n\" if /^[^\[]*\[\K([^]]+)[^{]*\{[^[]*\[\"\K([^\"]+)(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/' /path/to/file.log" > local.txt
我还转义了 glob 后的左括号,因为 perl 对此有抱怨。
另外,我认为您不需要在连接上强制使用伪 tty,因此您可能可以删除-t
。如果这给您带来麻烦,那么我会-T
首先尝试禁用伪 TTY 创建。
答案2
以下是 Guy 答案的几个替代方案。
我缩短了你的原始命令以使其(稍微)更易读:
perl -ne 'print "$1,$2,$3\n" if /^([^\[]*)(?:.*(?!SmsJob).)*/' /var/log/syslog
现在有了ssh
,如果你将 perl 代码放在双引号中,你可以使用qq{}
inside,而不是转义双引号。但是,你仍然需要转义变量$
:
ssh -i $id $user@$host 'perl -ne "print qq{\$1,\$2,\$3\n} if /^([^\[]*)(?:.*(?!SmsJob).)*/" /var/log/syslog'
更具可读性的替代方法是使用@choroba 评论中的建议:关闭并重新打开引号:
ssh -i $id $user@$host 'perl -ne ' "'" 'print "$1,$2,$3\n" if /^([^\[]*)(?:.*(?!SmsJob).)*/' "'" /var/log/syslog
或者稍微缩短一点,将第一部分放在双引号中:
ssh -i $id $user@$host "perl -ne '" 'print "$1,$2,$3\n" if /^([^\[]*)(?:.*(?!SmsJob).)*/' "'" /var/log/syslog
(使用本地 Ubuntu 16.04 和远程 Debian 9 进行测试)