2011-09-06 143 views
6

是否有可能以某種方式執行rake任務,只有當它沒有運行時 我想用cron來執行一些rake任務,但是如果以前的調用沒有完成,rake任務不應該啓動 謝謝rake檢查是否已經運行

回答

12

我用lockrun防止後臺任務運行多次(通過相同lockrun調用調用命令的時候,所以如果你需要從不同的調用路徑保護,那麼你就需要尋找其他的方法,這僅適用於)。

在crontab,您可以調用它像這樣:

*/5 * * * * /usr/local/bin/lockrun --lockfile=/tmp/this_task.lockrun -- cd /my/path && RAILS_ENV=production bundle exec rake this:task 
+1

謝謝你的答案從來沒有聽說過關於lockrun – Fivell

+2

有些系統中還有一些(通常位於/ usr/bin/flock) - 問題沒有指定操作系統。 –

+0

與flock有關的問題是你不能用一個以上的參數運行一個命令,所以'rake task_name'是兩個參數,因此失敗。 – yekta

5

對此的一般非rake特定解決方案是使用pid文件作爲鎖。您可以將rake任務包裝在腳本中,該腳本在運行rake時創建該文件,在rake完成運行時將其刪除,並在開始前檢查它。

不知道如果耙子有內置的東西,我什麼都不知道。

+0

我做了這樣的事情與PHP和每月一次鎖定文件莫名其妙沒有被刪除...所以我認爲這不是100%的解決方案 – Fivell

+1

如果將PID放在文件中,並檢查是否正在運行(而不僅僅是存在該文件),則可能可以更可靠地刪除該鎖。 – spike

+0

不錯的主意!謝謝 – Fivell

2

如果您只是想跳過這個rake任務,您還可以使用數據庫存儲有關任務進度的信息(例如,在開始和完成給定任務時更新字段),並在運行每個任務之前檢查該信息。然而,如果你想要一個類似隊列的行爲,你可能需要考慮創建一個守護進程來處理這些任務。這個過程非常簡單,給你更多的控制。這裏有一個非常好的railscast:Custom Daemon

守護進程方法也將阻止再次在每個任務上加載rails環境。如果你的rake任務頻繁,這特別有用。

6

此外,您還可以使用一個鎖文件,但在任務處理:

def lockfile 
    # Assuming you're running Rails 
    Rails.root.join('tmp', 'pids', 'leads_task.lock') 
end 

def running! 
    `touch #{lockfile}` 
end 

def done! 
    `rm #{lockfile}` 
end 

def running? 
    File.exists?(lockfile) 
end 

task :long_running do 
    unless running? 
    running! 
    # long running stuff 
    done! 
    end 
end 

這大概可以提取到一些一種模塊,但你明白了。

1

這裏是我的變體與文件鎖軌Rake任務。

在耙任務文件將這個(在命名空間,所以它不會與其他rake任務重疊):

def cron_lock(name) 
    path = Rails.root.join('tmp', 'cron', "#{name}.lock") 
    mkdir_p path.dirname unless path.dirname.directory? 
    file = path.open('w') 
    return if file.flock(File::LOCK_EX | File::LOCK_NB) == false 
    yield 
end 

用法:

cron_lock 'namespace_task_name' do 
    # your code 
end 

完整的例子:

namespace :service do 
    def cron_lock(name) 
    path = Rails.root.join('tmp', 'cron', "#{name}.lock") 
    mkdir_p path.dirname unless path.dirname.directory? 
    file = path.open('w') 
    return if file.flock(File::LOCK_EX | File::LOCK_NB) == false 
    yield 
    end 

    desc 'description' 
    task cleaning: :environment do 
    cron_lock 'service_cleaning' do 
     # your code 
    end 
    end 
end 
相關問題