Display terminal output on web browser? - ruby-on-rails

Here is my case:
I want to use a web browser to connect to a Rails application that runs this example code on the server side:
Dir.chdir path_typed_in_by_user
system "ls -la"
I want the output of "ls -la" to be displayed on the web browser.
Is this possible somehow?

This links may help you run command line command into ruby ...
http://zhangxh.net/programming/ruby/6-ways-to-run-shell-commands-in-ruby/
Calling shell commands from Ruby
http://blog.jayfields.com/2006/06/ruby-kernel-system-exec-and-x.html
%x[command].each do |f|
value = f
end

try in a controller:
Dir.chdir path_typed_in_by_user
#out = system `ls -la` # !! look here !! " change `
in a view:

Related

xonsh "which" equivalent - how to test if a (subprocess mode) command is available?

I would like to test (from xonsh) if a command is available or not. If I try this from the xonsh command prompt:
which bash
Then it works:
user#server ~ $ which bash
/usr/bin/bash
But it does not work from xonsh script:
#!/usr/bin/env xonsh
$RAISE_SUBPROC_ERROR = True
try:
which bash
print("bash is available")
except:
print("bash is not available")
Because it results in this error:
NameError: name 'which' is not defined
I understand that which is a shell builtin. E.g. it is not an executable file. But it is available at the xnosh command prompt. Then why it is not available inside an xonsh script? The ultimate question is this: how can I test (from an xonsh script) if a (subprocess mode) command is available or not?
import shutil
print(shutil.which('bash'))
While nagylzs' answer led me to the right solution, I found it inadequate.
shutil.which defaults to os.environ['PATH']. On my machine, the default os.environ['PATH'] doesn't contain the active PATH recognized by xonsh.
~ $ os.environ['PATH']
'/usr/bin:/bin:/usr/sbin:/sbin'
I found I needed to pass $PATH to reliably resolve 'which' in the xonsh environment.
~ $ $PATH[:2]
['/opt/google-cloud-sdk/bin', '/Users/jaraco/.local/bin']
~ $ import shutil
~ $ shutil.which('brew', path=os.pathsep.join($PATH))
'/opt/homebrew/bin/brew'
The latest version of xonsh includes a built-in which command. Unfortunately, the version included will emit an error on stdout if the target isn't found, a behavior that is not great for non-interactive use.
As mentioned in another answer, which exists in the current version of xonsh (0.13.4 as of 15/12/2022) so your script would work. However, it outputs its own error message so it's necessary to redirect stderr to get rid of it.
Also, unless you redirect its stdout as well (using all>), it migh be a good idea to capture its output so the final version would look like this:
#!/usr/bin/env xonsh
$RAISE_SUBPROC_ERROR = True
try:
bash = $(which bash err> /dev/null)
print(f"bash is available: {bash}")
except:
print("bash is not available")

Windows commands in ruby

How do I run a Windows command in an Ruby app?
I am trying to run something like:
output = `cd #{RAILS_ROOT}/lib && java HelloWorld #{param1} #{param2}`
I print the result of the line above and paste it to a command prompt in Windows and it works just fine. However, when i run app and hit this code, output is blank rather than have a string I get back from HellowWorld. In HelloWorld I do a System.out.print("helloworld")
The following:
output = `cmd.exe /C dir`
puts "OUTPUT #{output}"
Returns:
OUTPUT
Issue in JRuby 1.5.3 fixed in JRuby 1.5.5:
http://www.jruby.org/2010/11/10/jruby-1-5-5.html
Try to use File#join here. It will generate crossplatform path for you
http://apidock.com/ruby/File/join/class
my_path = File.join(RAILS_ROOT, "lib")
output = `cd #{my_path} && java HelloWorld #{param1} #{param2}`
Also you can execute your system commands this way:
`cd #{my_path} && java HelloWorld #{param1} #{param2}`
system("cd #{my_path} && java HelloWorld #{param1} #{param2}")
%x[cd #{my_path} && java HelloWorld #{param1} #{param2}]
Related topic: System call from Ruby
Backticks work fine for me. Try:
output = `dir`
to prove to yourself that it's working. At that point, your question is how to run a Java app from the command line, or why your particular app isn't work. Note that you can temporarily change the working directory like this:
Dir.chdir(File.join(RAILS_ROOT,'lib')) do
output = `...`
end

Calling Bash Commands With Multiple args From Ruby?

I write this code in my rails project.It's to execute a shell script ,But my shell script can catch #directdown only.
rails script
#cmd = "/downafile.sh #{#directdown} #{#file.id} #{#filename}"
`#{#cmd}`
shell script
echo $1 >> /tmp/ceshi.tmp
echo $2 >> /tmp/ceshi.tmp
echo $3 >> /tmp/ceshi.tmp
Thanks.
`` and system command works in similar manner.
But system method will return true on success.
Try with this:
#cmd = "/downafile.sh '#{#directdown}' '#{#file.id}' '#{#filename}'"
`#{#cmd}`
Try using puts #cmd to see the command generated and see whether the command is what you intended. If it is try executing it from the terminal to test whether your shell script works. I think the parameters #file.id and #filename value may be nil so on interpolation it will be replaced by "". puts their values also to check.
I don't know what is the meaning of `` in Ruby, but I think you can use the system function to invoke an external program. Something like,
#cmd = "/downafile.sh #{#directdown} #{#file.id} #{#filename}"
system(#cmd)
Hope it helps.

rails - Redirecting console output to a file

On a bash console, if I do this:
cd mydir
ls -l > mydir.txt
The > operator captures the standard input and redirects it to a file; so I get the listing of files in mydir.txt instead of in the standard output.
Is there any way to do something similar on the rails console?
I've got a ruby statement that generates lots of prints (~8k lines) and I'd like to be able to see it completely, but the console only "remembers" the last 1024 lines or so. So I thought about redirecting to a file - If anyone knows a better option, I'm all ears.
A quick one-off solution:
irb:001> f = File.new('statements.xml', 'w')
irb:002> f << Account.find(1).statements.to_xml
irb:003> f.close
Create a JSON fixture:
irb:004> f = File.new(Rails.root + 'spec/fixtures/qbo/amy_cust.json', 'w')
irb:005> f << JSON.pretty_generate((q.get :customer, 1).as_json)
irb:006> f.close
You can use override $stdout to redirect the console output:
$stdout = File.new('console.out', 'w')
You may also need to call this once:
$stdout.sync = true
To restore:
$stdout = STDOUT
Apart from Veger's answer, there is one of more way to do it which also provides many other additional options.
Just open your rails project directory and enter the command:
rails c | tee output.txt
tee command also has many other options which you can check out by:
man tee
If you write the following code in your environment file, it should work.
if "irb" == $0
config.logger = Logger.new(Rails.root.join('path_to_log_file.txt'))
end
You can also rotate the log file using
config.logger = Logger.new(Rails.root.join('path_to_log_file.txt'), number_of_files, file_roation_size_threshold)
For logging only active record related operations, you can do
ActiveRecord::Base.logger = Logger.new(Rails.root.join('path_to_log_file.txt'))
This also lets you have different logger config/file for different environments.
Using Hirb, you can choose to log only the Hirb output to a text file.
That makes you able to still see the commands you type in into the console window, and just the model output will go to the file.
From the Hirb readme:
Although views by default are printed to STDOUT, they can be easily modified to write anywhere:
# Setup views to write to file 'console.log'.
>> Hirb::View.render_method = lambda {|output| File.open("console.log", 'w') {|f| f.write(output) } }
# Doesn't write to file because Symbol doesn't have a view and thus defaults to irb's echo mode.
>> :blah
=> :blah
# Go back to printing Hirb views to STDOUT.
>> Hirb::View.reset_render_method
Use hirb. It automatically pages any output in irb that is longer than a screenful. Put this in a console session to see this work:
>> require 'rubygems'
>> require 'hirb'
>> Hirb.enable
For more on how this works, read this post.
Try using script utility if you are on Unix-based OS.
script -c "rails runner -e development lib/scripts/my_script.rb" report.txt
That helped me capture a Rails runner script's very-very long output easily to a file.
I tried using redirecting to a file but it got written only at the end of script.
That didn't helped me because I had few interactive commands in my script.
Then I used just script and then ran the rails runner in script session but it didn't wrote everything. Then I found this script -c "runner command here" output_file and it saved all the output as was desired. This was on Ubuntu 14.04 LTS
References:
https://askubuntu.com/questions/290322/how-to-get-and-copy-a-too-long-output-completely-in-terminal#comment1668695_715798
Writing Ruby Console Output to Text File

unix at command pass variable to shell script?

I'm trying to setup a simple timer that gets started from a Rails Application. This timer should wait out its duration and then start a shell script that will start up ./script/runner and complete the initial request. I need script/runner because I need access to ActiveRecord.
Here's my test lines in Rails
output = `at #{(Time.now + 60).strftime("%H:%M")} < #{Rails.root}/lib/parking_timer.sh STRING_VARIABLE`
return render :text => output
Then my parking_timer.sh looks like this
#!/bin/sh
~/PATH_TO_APP/script/runner -e development ~/PATH_TO_APP/lib/ParkingTimer.rb $1
echo "All Done"
Finally, ParkingTimer.rb reads the passed variable with
ARGV.each do|a|
puts "Argument: #{a}"
end
The problem is that the Unix command "at" doesn't seem to like variables and only wants to deal with filenames. I either get one of two errors depending on how I position "s
If I put quotes around the right hand side like so
... "~/PATH_TO_APP/lib/parking_timer.sh STRING_VARIABLE"
I get,
-bash: ~/PATH_TO_APP/lib/parking_timer.sh STRING_VARIABLE: No such file or directory
I I leave the quotes out, I get,
at: garbled time
This is all happening on a Mac OS 10.6 box running Rails 2.3 & Ruby 1.8.6
I've already messed around w/ BackgrounDrb, and decided its a total PITA. I need to be able to cancel the job at any time before it is due.
After playing around with irb a bit, here's what I found.
The backtick operator invokes the shell after ruby has done any interpretation necessary. For my test case, the strace output looked something like this:
execve("/bin/sh", ["sh", "-c", "echo at 12:57 < /etc/fstab"], [/* 67 vars */]) = 0
Since we know what it's doing, let's take a look at how your command will be executed:
/bin/sh -c "at 12:57 < RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE"
That looks very odd. Do you really want to pipe parking_timer.sh, the script, as input into the at command?
What you probably ultimately want is something like this:
/bin/sh -c "RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE | at 12:57"
Thus, the output of the parking_timer.sh command will become the input to the at command.
So, try the following:
output = `#{Rails.root}/lib/parking_timer.sh STRING_VARIABLE | at #{(Time.now + 60).strftime("%H:%M")}`
return render :text => output
You can always use strace or truss to see what's happening. For example:
strace -o strace.out -f -ff -p $IRB_PID
Then grep '^exec' strace.out* to see where the command is being executed.

Resources