I want to run a script (code.rb) every time the url /code is hit.
How do I run the script?
require 'sinatra'
get '/' do
#run the script
end
Either fork off another process:
system('ruby code.rb')
... or simply load the script into the current context:
load 'code.rb' # *not* require
You need to load the code to ensure that it is run each time; require will only load the code once on the first request, and then not again:
smagic:Desktop phrogz$ cat hi.rb
puts "hi"
smagic:Desktop phrogz$ cat test.rb
require 'sinatra'
get '/require' do
x = require_relative( 'hi.rb' )
"require sez #{x}"
end
get '/load' do
x = load( 'hi.rb' )
"load sez #{x}"
end
smagic:Desktop phrogz$ ruby test.rb
== Sinatra/1.1.2 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.2.7 codename No Hup)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop
hi
127.0.0.1 - - [16/Jan/2011 20:49:43] "GET /require HTTP/1.1" 200 16 0.0019
127.0.0.1 - - [16/Jan/2011 20:49:46] "GET /require HTTP/1.1" 200 17 0.0005
hi
127.0.0.1 - - [16/Jan/2011 20:49:52] "GET /load HTTP/1.1" 200 13 0.0009
hi
127.0.0.1 - - [16/Jan/2011 20:49:54] "GET /load HTTP/1.1" 200 13 0.0008
127.0.0.1 - - [16/Jan/2011 20:50:09] "GET /require HTTP/1.1" 200 17 0.0005
127.0.0.1 - - [16/Jan/2011 20:50:12] "GET /require HTTP/1.1" 200 17 0.0005
The output of hi comes before the request entry in the log; you can see that the requests to 'require' only output hi the first time, while requests to 'load' show hi each time. Here's the output of the server, where true indicates that the code in the file was actually run and false shows that it was not:
smagic:~ phrogz$ curl http://localhost:4567/require
require sez true
smagic:~ phrogz$ curl http://localhost:4567/require
require sez false
smagic:~ phrogz$ curl http://localhost:4567/load
load sez true
smagic:~ phrogz$ curl http://localhost:4567/load
load sez true
smagic:~ phrogz$ curl http://localhost:4567/require
require sez false
smagic:~ phrogz$ curl http://localhost:4567/require
require sez false
Related
This question already has answers here:
Does a `+` in a URL scheme/host/path represent a space?
(6 answers)
Closed 3 years ago.
I am having some issues with Ruby's OpenURI follow redirect functionality.
When going to a URL that contains %20 in it, and that redirects with a 30x, Ruby's OpenURI fails.
The exact same URL, with a + instead of %20 works.
Both the %20 and + versions work properly with curl -L (follow).
Code
require 'open-uri'
base = "http://software-engineering-handbook.com/Handbook"
puts "===> PASS: URI Open +"
result = open "#{base}/Video+Series"
p result.status
puts "===> PASS: Curl +"
puts `curl -LIsS "#{base}/Video+Series" | grep HTTP`
puts "===> PASS: Curl %20"
puts `curl -LIsS "#{base}/Video%20Series" | grep HTTP`
puts "===> FAIL: URI Open %20"
begin
result = open "#{base}/Video%20Series"
p result.status
rescue => e
puts "#{e.class} #{e.message}"
end
Output
===> PASS: URI Open +
["200", "OK"]
===> PASS: Curl +
HTTP/1.1 200 OK
===> PASS: Curl %20
HTTP/1.1 303 See Other
HTTP/1.1 200 OK
===> FAIL: URI Open %20
OpenURI::HTTPError 302 Found (Invalid Location URI)
I am not sure what is going on here. Tried HTTParty (although I know it is just a wrapper), hoping to see a different behavior, but it also fails.
The server is responding with an redirect to an invalid URI. curl is being lax about it, but Ruby is being strict.
If we print out the e.cause we get more information.
#<URI::InvalidURIError: bad URI(is not URI?): "http://software-engineering-handbook.com/Handbook/Video Series/">
And also by looking at the headers from curl -I 'http://software-engineering-handbook.com/Handbook/Video%20Series'...
HTTP/1.1 303 See Other
Server: Cowboy
Date: Sat, 28 Dec 2019 21:41:28 GMT
Connection: keep-alive
Content-Type: text/html;charset=utf-8
Location: http://software-engineering-handbook.com/Handbook/Video Series/
And, indeed, the server is returning an invalid URI. Spaces are not allowed in a URI path. Ruby's URI class will not parse it.
> URI("http://software-engineering-handbook.com/Handbook/Video Series/")
URI::InvalidURIError: bad URI(is not URI?): "http://software-engineering-handbook.com/Handbook/Video Series/"
from /Users/schwern/.rvm/rubies/ruby-2.6.5/lib/ruby/2.6.0/uri/rfc3986_parser.rb:67:in `split'
I've a array of elements and for each element, I've to make a get call using RestClient. However, I see a few of the array elements are being skipped.
total_hosts = []
puts "total_hosts initially = " + total_hosts.size.to_s
require 'rest-client'
total_hosts = %w{10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.9 10.0.0.10 10.0.0.11 10.0.0.12 10.0.0.13 10.0.0.14 10.0.0.15}
puts "total_hosts after adding = " + total_hosts.size.to_s
total_hosts.each { |host|
begin
sleep 1
RestClient.get("http://#{host}/get_my_build") { |response|
case response.code
when 200
if response.body.include?("Your build number is 10")
puts "Latest build on #{host}"
else
puts "Older build on #{host}"
end
when 404
puts "Exception on #{host} not reachable"
end
}
rescue => e
puts "Exception on #{host}"
end
}
puts "job completed"
Output :
Latest build on 10.0.0.3
Latest build on 10.0.0.4
Exception on 10.0.0.5
Latest build on 10.0.0.6
Latest build on 10.0.0.7
Latest build on 10.0.0.8
Latest build on 10.0.0.9
Exception on 10.0.0.10
Latest build on 10.0.0.11
Latest build on 10.0.0.12
Latest build on 10.0.0.13
Latest build on 10.0.0.14
Latest build on 10.0.0.15
I could see hosts 1 and 2 are missing in the output. If I run the same script after some time they might be listed in the output but some other hosts are missing.
Whenever your script encounters an HTTP Response that is not 200 or 404, your script does nothing. So, if a host has a temporary error, or a redirection, or tells you to try again, or simply gives you some information, or any of the other ~60 possible responses, you simply ignore that host completely.
My pumaconf.rb has this line:
stdout_redirect '/var/log/puma/puma.log', '/var/log/puma/puma-err.log', true
puma.log contains:
=== puma startup: 2016-09-07 23:33:01 +0000 === [4433] - Worker 0 (pid: 4436) booted, phase: 0
puma-err.log contains:
10.10.10.1 - - [08/Sep/2016:00:03:27 +0000] "GET /health HTTP/1.0" 200 - 0.0005
10.10.10.1 - - [08/Sep/2016:00:03:27 +0000] "GET /health HTTP/1.0" 200 - 0.0005
Any tips on what I may have incorrectly setup?
Edit:
A little more info on my side -- I set up a new test in a clone of the puma code, with the following config:
log_requests
stdout_redirect "t4-stdout", "t4-stderr", true
pidfile "t4-pid"
bind "tcp://0.0.0.0:10103"
rackup File.expand_path('../hello.ru', File.dirname(__FILE__))
daemonize false
And wrote a test around "200 OK should only be in stdout, not in stderr" and everything is passing.
I'm pretty stumped why spinning up a puma server from the base repo is acting so differently, but I will keep digging.
This question already has answers here:
Save modifications in place with awk
(7 answers)
Closed 8 years ago.
I have a task to receive such information from access log file (in common log format) using unix command line:
Count # of requests with status_code == 200
There is a piece of that log file (wich includes data for 1 day):
127.0.0.1 "1.1.1.1" - [02/Dec/2014:14:30:00 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 7
127.0.0.1 "1.1.1.1" - [02/Dec/2014:14:32:30 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 8
127.0.0.1 "1.1.1.1" - [02/Dec/2014:15:20:12 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 8
127.0.0.1 "1.1.1.1" - [02/Dec/2014:15:22:20 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 8
127.0.0.1 "1.1.1.1" - [02/Dec/2014:15:30:10 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 8
127.0.0.1 "1.1.1.1" - [02/Dec/2014:15:35:15 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 7
127.0.0.1 "1.1.1.1" - [02/Dec/2014:16:25:11 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 7
127.0.0.1 "1.1.1.1" - [02/Dec/2014:16:27:10 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 8
127.0.0.1 "1.1.1.1" - [02/Dec/2014:16:33:12 +0000] "POST /server/ad?uid=abc&type=INV HTTP/1.1" 200 3966 10
I use this:
$ awk -F[:\ ] '{count[$5]++}; $12 == 200 { hour[$5]++} END { for (i in hour) print i, count[i] }' acces_log.log
And receive this:
14 2
15 4
16 3
But there is a small tip: all results should be stored in file. I wonder, how can I do this from command line.
Regards
All Linux/Unix and DOS command lines understand the symbols <, <<, >, >> for redirection.
To redirect output to a file, use
awk '{....}' > outputFile
#------------^ -- redirection
This redirection will always create a new outputFile, even if one exists already.
To append (extra) data to a file use
awk '{ .... }' >> outputFile
#--------------^^ -- append
IHTH
I can't get Webrick to work with the servlet HTTPServlet::CGIHandler--I get an EACCES error:
[2012-12-06 01:38:02] ERROR CGIHandler: /tmp/cgi-bin:
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpservlet/cgi_runner.rb:46:in `exec': Permission denied - /tmp/cgi-bin (Errno::EACCES)
from /Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpservlet/cgi_runner.rb:46:in `<main>'
[2012-12-06 01:38:02] ERROR CGIHandler: /tmp/cgi-bin exit with 1
[2012-12-06 01:38:02] ERROR Premature end of script headers: /tmp/cgi-bin
localhost - - [06/Dec/2012:01:38:02 MST] "GET /cgi/my_prog.cgi HTTP/1.1" 500 326
- -> /cgi/my_prog.cgi
Here are the permissions I set:
~/ruby_programs$ cd /
/$ ls -al tmp
lrwxr-xr-x# 1 root wheel 11 Jul 3 2011 tmp -> private/tmp
/$ cd tmp
/tmp$ ls -al
total 0
drwxrwxrwt 8 root wheel 272 Dec 6 01:08 .
drwxr-xr-x# 6 root wheel 204 Mar 27 2010 ..
drwxr-xr-x 3 7stud wheel 102 Dec 6 01:25 cgi-bin
/tmp$ cd cgi-bin/
/tmp/cgi-bin$ ls -al my_prog.cgi
-rwxr-xr-x 1 7stud wheel 123 Dec 6 01:09 my_prog.cgi
My server program(1.rb):
#!/usr/bin/env ruby
require 'webrick'
include WEBrick
port = 12_000
dir = Dir::pwd
server = HTTPServer.new(
:Port => port,
:DocumentRoot => dir + "/html"
)
server.mount("/cgi", HTTPServlet::CGIHandler, "/tmp/cgi-bin")
puts "Listening on port: #{port}"
Signal.trap('SIGINT') { server.shutdown }
server.start
Running my server program:
~/ruby_programs$ ruby 1.rb
[2012-12-06 01:37:58] INFO WEBrick 1.3.1
[2012-12-06 01:37:58] INFO ruby 1.9.3 (2012-04-20) [x86_64-darwin10.8.0]
Listening on port: 12000
[2012-12-06 01:37:58] INFO WEBrick::HTTPServer#start: pid=4260 port=12000
I entered this address in my browser:
http://localhost:12000/cgi/my_prog.cgi
This was displayed in my browser:
Internal Server Error
Premature end of script headers: /tmp/cgi-bin WEBrick/1.3.1
(Ruby/1.9.3/2012-04-20) at localhost:12000
Here's my cgi script(/tmp/cgi-bin/my_prog.cgi):
#!/usr/bin/env ruby
require 'cgi'
cgi = CGI.new
puts cgi.header
puts "<html><body>Hello Webrick</body></html>"
The only way I can get WEBrick to execute cgi files in a directory other than the root, is to use the HTTPServlet::FileHandler servlet:
port = 12_500
...
cgi_dir = File.expand_path("~/ruby_programs/cgi-bin")
server.mount("/cgi", HTTPServlet::FileHandler, cgi_dir)
Then the url used to execute a .cgi file located in the cgi_dir is:
http://localhost:12500/cgi/my_prog.cgi
Apparently, when you write:
server = HTTPServer.new(
:Port => port,
:DocumentRoot => "./html" #Regular files served/.cgi files executed out of this dir
)
Webrick automatically "mounts" an HTTPServlet::FileHandler to handle requests to the :DocumentRoot directory, e.g.
http://localhost:12500/my_html.htm
which will serve files out of the ./html directory (i.e. a directory called html located below the directory from which your program is running). The HTTPServlet::FileHandler will also execute files in that directory if they have a .cgi extension.
If you explicitly use mount() to add an HTTPServlet::FileHandler to another directory, e.g.
cgi_dir = File.expand_path("~/ruby_programs/cgi-bin")
server.mount("/cgi", HTTPServlet::FileHandler, cgi_dir)
then WEBrick will also serve files from that directory and execute files in that directory that have a .cgi extension.
I haven't found a way to configure WEBrick to only serve files out of the :DocumentRoot directory and only execute .cgi files in another directory.
See "Gnome's Guide to WEBrick" here:
http://microjet.ath.cx/webrickguide/html/
In my case I had similar problems because of incorrect file permissions and really incorrect headers. Permissions of CGI-script should be like this:
~/ruby_projects/cgi_webrick/cgi
ls -l
-rwxr-xr-x 1 me me 112 Sep 20 20:29 test.cgi
My server code looks very similar (placed in ~/ruby_projects/cgi_webrick/), but with different handler.
#!/usr/bin/env ruby
require 'webrick'
server = WEBrick::HTTPServer.new :Port => 1234
server.mount "/", WEBrick::HTTPServlet::FileHandler , './'
trap('INT') { server.stop }
server.start
If you run server script ruby my_server_script.cgi, it will serve any scripts from root or other directory. In my case I can access http://localhost:1234/cgi/test.cgi (script placed in cgi subfolder), and http://localhost:1234/test.cgi (placed in the root directory from which server is started).
My test script:
#!/usr/bin/ruby
require 'cgi'
cgi = CGI.new
puts cgi.header
puts "<html><body>This is a test</body></html>"