perl 两个连续的反勾 shell 命令不运行
我正在尝试编写 perl 脚本来管理亚马逊 ec2 实例。在我的部分代码中,我有两个 shell 命令,当我调用它们时,第一个命令运行,但第二个命令不运行。我似乎无法找到一个很好的解释。代码如下:
$run_instances = 'ec2-run-instances ami-8e1fece7 -k mykey -t t1.micro';
$outp = `$run_instances`;
$outp =~ /INSTANCE\s+(i-\w+)\s/;
$instance_id = $1;
$describe_instances = "ec2-describe-instances $instance_id";
$outp = `$describe_instances`;
$outp =~ /(ec2-(\d+-\d+-\d+-\d+).\S+)/;
问题是 $outp
这里有 $run_instances
的输出。有一段时间我不明白为什么我得到了错误的输出;然后我意识到 $describe_instances
命令没有运行。
我查看了从 Linux shell 调用的 $describe_instances
的值,它工作得很好。我从另一个 Perl 脚本调用它,它工作得很好。
然后我给了 $outp
运行 $run_instances
时捕获的输出 ($outp = "INSTANCE ......"
)。它有效,所以我想到当这两个命令连续运行时,第二个命令不会运行。
还要注意的另一件事是,当每次 $run_instances
工作但 $describe_instances
不工作时,我将上面的代码放入循环中。
如果您能对此提供一些说明,我将非常高兴:)
谢谢
I am trying to write perl script for managing amazon ec2 instances. In part of my code, I have two shell commands, and when I invoke them, the first runs but not the second. I cannot seem to find a good explanation for this. Here is the code:
$run_instances = 'ec2-run-instances ami-8e1fece7 -k mykey -t t1.micro';
$outp = `$run_instances`;
$outp =~ /INSTANCE\s+(i-\w+)\s/;
$instance_id = $1;
$describe_instances = "ec2-describe-instances $instance_id";
$outp = `$describe_instances`;
$outp =~ /(ec2-(\d+-\d+-\d+-\d+).\S+)/;
The problem is $outp
here has the output of $run_instances
. For some time I could not understand why I was getting the wrong output; then I realised that $describe_instances
command does not run.
I looked at the value of $describe_instances
, called that from the Linux shell, and it worked fine. I called it from another Perl script, and it worked fine.
Then I gave $outp
the output that is captured when $run_instances
runs ($outp = "INSTANCE ......"
). It worked, so I got the idea that somehow when these two commands run consecutively the second does not run.
One more thing to note is that when I put above code in a loop every time $run_instances
works but $describe_instances
does not.
I would be really happy if you could provide some light on this :)
Thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的程序有一些危险信号。我将在下面讨论它们,并在最后提出一种更好的编写代码的方法。
危险信号 1
您问题中的代码尝试使用反引号执行外部命令并假设成功。您应该始终检查对操作系统的任何调用的状态。失败的
`$command`
— 还有称为qx//
或readpipe
— 以一种或多种方式显示自身,具体取决于是否命令已执行但失败或尝试执行命令是否失败:$?
非零。$!
包含失败的描述。使用 Perl,
`$command`
执行一个子 shell 以便执行$command
,因此子 shell 可能是执行并失败的程序,eg,命令语法错误。下面示例中的一个命令在我的机器上成功了。
输出:
Red Flag 2
请注意,例如输出行,
我没有编写生成此警告的代码。相反,它会自动发生,因为我使用
use warnings
行启用了警告编译指示。如果您启用了警告,Perl 至少已经给您提供了有关问题原因的提示,因此我假设您没有启用警告。这是另一个危险信号。警告可以帮助您。始终为任何重要的程序启用它们。
危险信号 3
最后,您无条件地使用正则表达式捕获变量
$1
,当匹配失败并且您从不同的匹配中获取捕获的值时,这种习惯将导致令人惊讶的错误。您应该始终将$1
、$2
和朋友的使用包装在条件(eg)内,建议的修复
位于代码顶部附近,紧接在 行,
shebang 行,您应该立即添加我也推荐的
但这可能需要更多工作来清理您的代码。我们随时帮助您理解并克服在这一有价值的努力中发现的任何问题。
使用下面的
output_of
捕获命令的输出或通过适当的诊断来终止。您问题中的代码部分变为
通过这些更改,您的代码将为处理
ec2-run-instances
和ec2-describe-instances 的输出中的所有故障模式提供标准错误诊断
而不是让你想知道出了什么问题。Your program has a few red flags. I discuss them below and at the end suggest a better way to write your code.
Red Flag 1
The code from your question attempts to execute external commands with backticks and assumes success. You should always check the status of any call to the operating system. A failed
`$command`
—also known asqx//
orreadpipe
—makes itself known in one or more ways depending on whether the command executed and failed or whether attempted execution of the command failed:$?
is non-zero.$!
contains a description of the failure.With Perl,
`$command`
executes a subshell in order to execute$command
, so the subshell may be the program that executes and fails, e.g., for bad command syntax.Exactly one command in the example below succeeds on my machine.
Output:
Red Flag 2
Note for example the line of output
I didn't write the code that generated this warning. Instead, it happened automatically because I enabled the warnings pragma with the line
use warnings
. Had you enabled warnings, Perl would have already given you at least a hint about the cause of your problem, so I assume you didn't enable warnings.This is another red flag. Warnings are there to help you. Always enable them for any non-trivial program.
Red Flag 3
Finally, you're using regex capture-variable
$1
unconditionally, and this habit will lead to surprising bugs when the match fails and you get a captured value from different match. You should always wrap uses of$1
,$2
, and friends inside a conditional, e.g.,Recommended Fixes
Near the top of your code just after the shebang line, you should immediately add the line
I'd also recommend
but that will likely require more work to clean up your code. We're here to help you understand and overcome any issues you find in that worthwhile effort.
Use
output_of
below to capture a command's output or die with an appropriate diagnostic.The section of code from your question becomes
With these changes, your code will supply on the standard error diagnostics for all failure modes in processing output from
ec2-run-instances
andec2-describe-instances
instead of leaving you to wonder what went wrong.在以下内容之后 $outp 是已定义还是未定义:
您是否已验证 $instance_id 设置为您期望的值?
$的值是多少!和$?在非工作反引号命令之后?
非工作命令是否正在向 stderr 写入任何内容?
Is $outp defined or undefined after the:
Have you verified that $instance_id is set to what you expect?
What are the values of $! and $? after the non-working backtick command?
Is anything being written to stderr by the non-working command?
我怀疑问题出在这一行:
$1
是一个全局变量。人们永远不应该使用未经测试的$1
等,因为它:(来自perldoc perlvar)
换句话说,如果没有匹配,则不会被覆盖。您可能会做这样的事情:
我尽量不使用未经测试的
$1
,当然有很多方法可以确保它来自正确的地方。I suspect the problem is this line:
$1
is a global variable. One should never use$1
et al untested, since it:(from perldoc perlvar)
In other words, it is not overwritten if there is no match. What you might do is something like this:
I try never to use
$1
untested, and of course there are many ways to make sure it comes from the right place.