By sandroraess
Rails: Rails 6.0.3.4
Ruby: ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
Nginx: nginx version: nginx/1.18.0 (Ubuntu)
Phusion Passenger: 5.3.2
In my controller, I want to run a system command. It works locally but it doesn’t work remotely.
Code
I create a markdown-file and store it inside my public folder.
dir = Rails.root.join('public', 'pancritic')
Dir.mkdir(dir) unless Dir.exist?(dir)
File.open(dir.join("pancritic.md"), 'w+') do |file|
file.write(@inputs[:text])
end
After storing the file in /public/pancritic, I want to run a system command:
`pancritic -s -o #{dir}/pancritic.pdf #{dir}/pancritic.md`
This code converts the markdown-file to a pdf. The output is stored in the same folder.
But in production (on Digital Ocean), the command does not create the pdf.
Does the system command work on Digital Ocean?
When I ssh as a non-root user into digital ocean, cd into public/pancritic and enter
pancritic -s -o pancritic.pdf pancritic.md
the pdf gets created. I assume that there is nothing wrong with the command itself.
What could be the reason why the command does not work in Production?
What I tried so far
I’ve tried other ways of entering system commands. They all work locally, but none of them work in production:
system("pancritic -s -o #{dir}/pancritic.pdf #{dir}/pancritic.md")
Open3.popen3("pancritic -s -o #{dir}/pancritic.pdf {dir}/pancritic.md") do |stdin, stdout, stderr, wait_thr|
...
end
%x[pancritic -s -o #{dir}/pancritic.pdf {dir}/pancritic.md]
Full Code
def pancritic_editor
if params[:inputs].present?
@inputs = OpenStruct.new(params[:inputs])
else
@inputs = OpenStruct.new()
end
start_markdown ='
# Introduction
Text
'
@inputs[:text] = @inputs[:text] ? @inputs[:text] : start_markdown
dir = Rails.root.join('public', 'pancritic')
Dir.mkdir(dir) unless Dir.exist?(dir)
File.open(dir.join("pancritic.md"), 'w+') do |file|
file.write(@inputs[:text])
end
`pancritic -s -o #{dir}/pancritic.pdf #{dir}/pancritic.md`
until File.exist?("#{dir}/pancritic.pdf")
sleep 1
end
File.open("#{dir}/pancritic.pdf") do |file|
@stuff = Stuff.create(filename: "pancritic_editor #{DateTime.now}")
@stuff.file.attach(io: file, filename: "basic-markdown-editor-#{Date.today.to_s}.pdf")
end
File.delete("#{dir}/pancritic.md")
File.delete("#{dir}/pancritic.pdf")
end
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hello,
The issue you’re encountering is likely due to the system environment under which your Rails app is running in production.
When you SSH into your Digital Ocean server and execute the pancritic command, you are in a full-featured shell environment with all environment variables correctly set, including PATH.
However, when the Rails application tries to execute the same command, it does so under a different, limited system environment, and it’s possible that it can’t find the pancritic command because it’s not in the PATH that the Rails application has access to.
To resolve the issue, you have a couple of options:
Provide full path to the command in the script. If you know the full path where pancritic is installed, you could modify your script to use the full path instead of just the command. You can find the full path by running which pancritic when you’re SSH’ed into the server. Then in your code, replace all instances of pancritic with that full path.
Modify the environment for the Passenger process. You could modify the Passenger configuration to include the correct PATH. This would be done in the Passenger configuration file (usually located at /etc/nginx/passenger.conf or similar). You could add an environment variable directive inside the http block like so:
http {
...
passenger_env_var PATH /usr/local/bin:/usr/bin:/bin;
...
}
Ensure the paths specified in the PATH variable include the path to your pancritic command. Restart Nginx after making these changes.
One additional thing to consider: The user that the Rails application is running as in production must have the necessary permissions to run the pancritic command and to write to the directories in question.
Also, if pancritic relies on other system resources (like temporary directories or other command-line tools), you’ll need to ensure that the Rails application has the necessary permissions to access those as well.
Lastly, to help debug this, you could modify your command execution in your Rails application to capture STDERR, which may provide more information about why the command is failing. Using Open3 to execute the command would allow you to capture and log the STDERR output.
Best,
Bobby
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.