如何在Rake任务中执行命令?

20

我有一个Rails应用程序中的rake任务。我想在rake任务中运行命令行命令。我该怎么做?我尝试了以下方法,但失败了:

desc "Sending the newsletter to all the users"
task :sending_mail do
  run "cd #{RAILS_ROOT} && ar_sendmail -o -t NewsLetters -v"
  system "cd #{RAILS_ROOT} && ar_sendmail -o -t NewsLetters -v &"
end

上述运行命令会抛出“run方法未定义”错误,而系统命令不会抛出任何错误,但也没有执行。
3个回答

29

Rake内置任务 sh

这可能是最好的方法:

task(:sh) do
  sh('echo', 'a')
  sh('false')
  sh('echo', 'b')
end

这个界面与Kernel.system相似,但:

  • 如果返回值!= 0,则会中止,因此上面的代码永远不会到达echo b
  • 输出结果之前会先打印命令本身

1
对我来说,这似乎也是最好的方法。 - Florian Loch

7

run 被Capistrano和其他工具用于启动命令,但是Rake通常使用Kernel#system

你的命令可能已经被执行了,但却没有起作用。为什么不创建一个独立测试的包装脚本,或者尝试使用完整路径来执行:

newsletter_script = File.expand_path('ar_sendmail', RAILS_ROOT)

if (File.exist?(newsletter_script))
  unless (system(newsletter_script + ' -o -t NewsLetters -v &'))
    STDERR.puts("Script #{newsletter_script} returned error condition")
  end
else
  STDERR.puts("Could not find newsletter sending script #{newsletter_script}")
end

将脚本放在scripts/目录下似乎很奇怪。

system调用应该在成功时返回true。如果不是这种情况,要么脚本返回了错误代码,要么命令无法运行。


嗨,tadman,谢谢你的回答...我刚刚复制了你的代码并尝试了一下,但是结果不如预期...你能告诉我File.expand_path是做什么用的吗? - palani
你好Tadman,你的脚本正在寻找文件 Rails_Root/ar_sendmailer。但这不是一个文件,而是从Rails应用程序根目录调用的命令。比如[/home/username/railsapp]$ar_sendmail -o -t NewLetter -V . 所以我需要在Rails应用程序的根目录下运行这个命令,请帮助我。 - palani
File.expand_path 用于扩展路径。它可以正确地将两个路径连接在一起,例如将 ar_sendmail 添加到您的 Rails 路径中,无论那是什么。它还可以消除像 ../../ 这样的内容,为您提供正确的完整路径。 - tadman
你需要知道 ar_sendmail 的位置,否则你将无法正确启动它。你的 shell 有一个 PATH,它可能与 Ruby 使用的不同,这可能会使脚本在不在当前目录时仍能正常工作。 - tadman

6

Rake有一个特定的方法来运行shell命令,#sh。它的缺点是使用/bin/sh而不是bash。要从Rake的sh方法中使用bash,请参见此重复问题的答案:https://dev59.com/fmkw5IYBdhLWcg3wlbd3#34523379 - Binary Phile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接