Discrepancies when executing a command in Rails controller vs Rails console - ruby-on-rails

I am trying to run the df command to display statistics of the disks which are attached to my server. However, it always returns the size of the disk as 0. If I run the same command in the rails console within the production environment, it returns the size of the disk.
Here's how my code is structured,
class Disk
def self.metrics
`df -h`
end
end
And this is how I call it in the controller,
class DiskController
def metrics
#metrics = Disk.metrics
end
end
But it always returns nil when I try to see the result in the view. The same command however works in the Rails console.
I've tried using system, POPEN but everything returns the same result.
Also, the same thing works in development (Mac OSX) but not in production (Linux Ubuntu).

Your console is running under the user you have logged in. Your Rails app is running under the user, dedicated to run your web server. I believe call to whoami from within the controller code will show the user name. This user is likely to be restricted to run df command. Though this is not recommended, the possible solution would be to grant this user to execute df command (via /etc/sudoers.)
I would go with another approach, though. I would add a cron job, that will execute df -h on behalf of any permitted user and put the output inside some text file within your project tree. The controller might then read this file to show the disk usage info.
I understand that the information might be slightly obsolete, but since one might execute the cron job each, say, minute, it should be acceptable. The advantage of this approach would be that web server still won’t have an access to system commands.

Related

How to display log for Rails application?

I have a rails app and I would like to display the log in the app itself. This will allow administrators to see what changes were recently made without entering the console and using the file with the logs. All logs will be displayed in the application administration. How is it possible to implement and what kind of gems do I need to use?
You don't need a Gem.
Add a controller, read the logfiles and render the output in HTML.
Probably need to limit the number of lines you read. Also there might be different log files to chose from.
I don't think this is a good idea though. Log files are for finding errors and you should not need them in your day to day work, unless you manage ther server.
Also they might contain sensitive data (CC Numbers, Pwds, ...) and it might get complicated when you use multiple servers with local disks.
Probably better to look at dedicated tools for this and handle logs outside of your application.
Assuming that you have git associated with your application or git bash installed in your system.
For displaying log information for the development mode, migrate to your application folder in your console/terminal and type tail -f log/development.log

Can Rails pass a shell command to the local machine?

I am trying to get rails to select document attachments, then kick off the email client with the documents attached.
I have it working on my development laptop. If I build a string with the appropriate parameters and pass that to system() then it kicks off the email client with the attachments..
The string looks something like
#email_content = "C:\Program Files (x86)\IBM\Lotus\Notes\notes.exe"
"Mailto:?Attach=C:\Users\cm\RubymineProjects\technical_library\public\images\1\8302_printed.pdf
The first part calls the notes exe and the second part starts and email with the attachments. That worked fine on my laptop.
However, when I moved it to the server, it isn't kicking off the email client. I believe that it is because the shell commands are trying to execute on the server, not on the client.
Is it possible to run a shell command on the client machine? I am trying to get this working with Windows first and then the Mac environmemnt. I tried changing the C:\ to the machine name. i.e. \chrislaptop\Program Files (x86)\IBM\Lotus\Notes\notes.exe. but that didn't work.
No, fortunately that is not possible.
Imagine what happens when a request to some random page on the internet could trigger shell scripts on your local computer...
Arbitrary code execution escaping the browser is too invasive-- your app should not have access to the client's machine.
However, some applications may support URIs that open specific applications outside the browser. You generally see this more on mobile devices, but Spotify for example supports links that look like: spotify:artist:5lsC3H1vh9YSRQckyGv0Up which asks the user whether it is ok to open the Spotify application.
https://news.spotify.com/us/2008/01/14/linking-to-spotify/

Neo4J web console has stats for my embedded data, but cannot query it

I'm currently evaluating Neo4J (2.0M3), and in an attempt to get some kind of visualisation and query-exploration (I haven't succeeded yet!), I switched from using the Test DB to an Embedded DB, and have a Server that I can start up when required.
I understand how to get my node and relationship data written to the data directory of my choice (via How to explore databases created by an embedded-Neo4j Java application and stored outside the /data directory?), and how to configure the Server/web console to point to that directory. Sure enough, the Dashboard does show the data counts I expect, but no Cypher query I try - not even the ones that work fine in my unit tests - return any nodes. Simple lookups by name and Id all fail.
Can anyone explain the inconsistency? This happens with a vanilla Server install, with data written to the default graph.db directory, as well as with different directories. The paths under 'Server Info' are all what I expetc to see.
Another thing I don't understand: why can I not have my own Server running, and create a GraphDatabaseFactory/GraphDatabaseService in code that will accept a server URI, which will allow me to use the standard Java API and see live updates in the web console without having to stop/start the server each time?
You can set up your embedded java project to even start a server, see http://www.cakesolutions.net/teamblogs/2012/05/23/enabling-neo4j-web-admin-tool-on-the-embedded-server-using-spring-data/

securely run linux command line app from asp.net mvc app under mono

We have an internal and external facing asp.net mvc app running under mono on ubuntu 10.04 LTS. There is also a complicated (native, not mono) command line app that users use on the same server. They log on via ssh to do this. We have the security for the ssh users pretty locked down, so they can't do very much other than run the command line app.
The users of these apps have to:
login via ssh to the server, run the command line app with whatever command line switches are required which then does some long running processing and puts a report in the db of the web app.
Login to the web app, then set some options for publishing a report via the web app.
The users of the apps want to skip step 1 and do it all in the web app. I am thinking of creating a service that regulary polls the db for command line app jobs to run. The jobs would be created by the users as desired in the web app.
The problem is, the users want a box in the web app where they can just fill in any command line options. But I don't want them to do something like this:
-a dothis -b dothis & rm importantfile.txt
...in case the user's credentials to the web app are somehow compromised. I want to make sure that only that command line app can be used and nothing else. I am thinking of preventing the characters ! | < > & / \ $ ( ) from being allowed, which looks like are not required by the command line app.
Is that good enough? Are there any other shell tricks I should know about? Should I take a different approach?
I really don't want to have to write some sort of parser for the arguments that the users supply, because there are a ton of them that the users like to use.
Instead of running the command line as a shell command (launching the shell to launch the program), can you launch the program itself as a new process? I believe that's what the answer here is doing: Execute a command line utility in ASP.NET . If the actual program is launched as a process, rather than a shell, then things like & or rm will just be arguments to the command line utility, which should be fine if the command line utility checks for bad inputs.
If that's not feasible (although it's probably the better option), replacing all single quotes with single quote escape sequences, then placing single quotes around each of the arguments (split the string with a space as the delimeter), could provide a similar effect. Instead of making sure you avoid all possible bad characters (; can be used similarly to & in many shells), you only need to make sure that the provided arguments can't escape out of the single quotes. (You might also want to check for single quote surrounded arguments beforehand, to avoid double quoting them, and don't cound escaped spaces when splitting up arguments, etc., so that the users can provide arguments that need spaces).

Will "system()" call in Ruby wait until it finishes?

I'm new to ruby on rails. I want to call a system command to analyze an uploaded file in my Rails application. Something as follows:
after_save :analyse #post processing call
def analyse
command = "./c_executable " + Rails.root.to_s + "/output_csv_file"
system(command)
if FileTest.exists?(Rails.root.to_s + "/output_csv_file")
parse_csv
end
end
It runs fine on my local machine, but for some reason the function "parse_csv" won't get called on the server(dreamhost). However, I manually call the c_executable system command on the server and it outputs the csv file without a problem. Could anyone tell me what might be causing the problem here? I was thinking the system call takes some time to finish on the server. If that's the case, I'm wondering if there is a way to tell rails to wait until the system() call finishes execution. Thanks in advance!
The system call should block until the command inside is finished. It is possible that the file is not being created as you intended which might preclude that part of your app from running.
You might want to use a different way of constructing your path to be sure you're getting it right:
csv_path = File.expand_path('output_csv_file', Rails.root)
unless (system('./c_executable', csv_path))
# Could't execute system command for some reason.
end
if (File.exists?(csv_path))
# ...
end
When making system calls it's generally a good idea to specify the full path to the executable as your application PATH may be different from what you expect.
My first guess is that it's a permissions error. Do you know what user the web/app server is running as and see if it has the correct permissions to both read/execute the command and write the output file.
I'll answer my own question now. After spending several days of testing and googling, it turns out that dreamhost doesn't allow these kind of non built-in system calls. I'll have to change my hosting service.

Resources