如何在Rails生产环境中无需Whenever Gem与Rails Runner运行Cron任务?
Got it, let's work through setting up your cron task without relying on the Whenever gem or the resource-heavy rails runner. Here's a straightforward, efficient approach tailored to your needs:
First, make a standalone Ruby script that loads only what's necessary to run your Cart.send_reminder method. This avoids the full Rails app load overhead that comes with rails runner, but still keeps things maintainable.
Create a file at script/cart_reminder.rb in your Rails app with this content:
# script/cart_reminder.rb # Load the core Rails environment (minimal but sufficient for model and mailer functionality) require_relative '../config/environment' # Explicitly call your method Cart.send_reminder
Test this script manually first to ensure it works:
cd /path/to/your/rails/app bundle exec ruby script/cart_reminder.rb
Next, set up the cron schedule to run this script every 30 minutes.
- Open your user's crontab editor:
crontab -e - Add this line to the file (replace
/path/to/your/rails/appwith your actual application directory):*/30 * * * * cd /path/to/your/rails/app && bundle exec ruby script/cart_reminder.rb >> log/cart_reminder.log 2>&1
Let's break down what this cron line does:
*/30 * * * *: Runs the task every 30 minutes, every hour, every day, every month, every weekday.cd /path/to/your/rails/app: Ensures the script runs from the correct directory so relative paths (like toconfig/environment.rb) work.bundle exec ruby script/cart_reminder.rb: Usesbundle execto ensure you're using the exact gem versions specified in yourGemfile.lock, then runs the script.>> log/cart_reminder.log 2>&1: Logs both standard output and errors to a dedicated log file, making it easy to debug if something goes wrong.
If you want to cut down even more on load time and don't need the full Rails environment, you can create a script that only loads Active Record and your required mailer logic. This is more manual but avoids loading parts of Rails you don't use.
Create script/lightweight_cart_reminder.rb:
# script/lightweight_cart_reminder.rb require 'active_record' require 'action_mailer' # Load production database config db_config = YAML.load_file(File.expand_path('../config/database.yml', __dir__))['production'] ActiveRecord::Base.establish_connection(db_config) # Define the Cart model with just the method you need class Cart < ActiveRecord::Base def self.send_reminder send_reminder_email("example@example.com") end # Copy or require the send_reminder_email logic here def self.send_reminder_email(email) # Load your SMTP settings (adjust path to your config file if needed) smtp_config = YAML.load_file(File.expand_path('../config/application.yml', __dir__))['smtp_settings'] ActionMailer::Base.smtp_settings = smtp_config # Replace with your actual email sending code # CartReminderMailer.reminder_email(email).deliver_now end end # Execute the method Cart.send_reminder
Update your cron line to use this script instead if you go this route.
Key Notes:
- Always test your cron script manually before relying on it to catch any path or dependency issues.
- If cron can't find
bundle, use the absolute path tobundle(you can find it withwhich bundle). - Rotate your log file regularly (e.g., with
logrotate) to prevent it from growing too large.
内容的提问来源于stack exchange,提问作者Cannon Moyer

