Call Ruby from a VBScript - ruby-on-rails

Hey I have been working with ruby and vbscript lately. There is a scenario where I need to call a ruby script from another vbscript and I am stuck there. I tried this code,
Set newobj = CreateObject("WScript.shell")
obj = newobj.Run("ruby E:\rubyfile.rb > D:\newdoc.txt",1,true)
but the ruby script is not giving the result. Am I doing it right or is there some other way to do it?
If the ruby script is executed separately then the results are generated, so the problem is not with the ruby script.

You need a shell (%comspec% /c) to get a shell's feature like > redirection. So change
obj = newobj.Run("ruby E:\rubyfile.rb > D:\newdoc.txt",1,true)
to
nRet = newobj.Run("%comspec% /c ruby E:\rubyfile.rb > D:\newdoc.txt",1,true)
(Study the docs for .Run to see the reason for nRet instead of obj and spend a thought on the lousy-ness of the name "newobj")

Related

How to run a function without using any functions defined in the script in Lua

I am trying to loadstring a string and run it as a function. Here is my problem:
a = "hello"
loadstring("print(a)")()
I dont want the code above to use any vars/funcs outside of it. My goal is to make the script above print nil since a isnt defined inside the loadstring.
Sorry if the question is very brief. It was hard to explain my problem.
Your variable a lives in the global environment. To keep your chunk from seeing it, you need to give it a different environment. In Lua 5.1, you'd do that like this:
a = "hello"
local chunk = loadstring("print(a)")
setfenv(chunk, {print = print})
chunk()
In Lua 5.2 or newer, you'd do that like this:
a = "hello"
load("print(a)", nil, "t", {print = print})()
It's important to note that print isn't magic. It won't be in the new environment unless you put it there explicitly, like I did.

Jenkins file can we use the IF statement

in Jenkins file one of the variable is having the comma separated values like below.
infra_services=[abc,def,xyz]
when I write the below code it was throwing an error.
if ("{$Infra_Services}".contains("xyz"))
then
echo "$Infra_Services"
fi
yes you can do if statements in a Jenkinsfile. However if you are using declarative pipeline you need to brace it with the step script.
Your issue comes from the fact you did not put any double quotes around "abc" and all the elements of your array
infra_services=[abc,def,xyz]
​
A second error will raise after you fix this. If infra_services is an array, to manipulate it you should not try to cast it as string. It should throw when you do "{$Infra_Services}"
here is a working example
​def Infra_Services = ["abc","def","xyz"]
if (Infra_Services.contains("xyz")) {
println "found"
}​​
My advice is to test your groovy before running it on jenkins, you will gain precious time. Here is a good online groovy console I use to test my code. running the groovy console from terminal is an alternative
https://groovyconsole.appspot.com/

Issues while using sqlplus with ruby

I want to use sqlplus within ruby. Dont want to use any gems[bec I cannot get it installed on our servers without much help from other teams ..etc] and want to keep it very minimal.
I am trying something as simple as this in my ruby script:
`rlwrap sqlplus user/pswd#host << EOF`
`set serveroutput on;`
`commit;` #ERROR1: sh: commit: not found
sql = "insert /*+ APPEND*/ INTO table(col1, col2) values (#{data[0]},#{data[1]});"
`#{sql}` #ERROR2: sh: Syntax error: "(" unexpected
Can anyone help me with ERROR1 and ERROR2 above
Basically for "commit: not found" I think its getting executed on shell rather than in sqlplus. However seems like "set serveroutput on" seems to execute fine !
For ERROR2, I am clueless. I also tried using escape slash for the "/" in the sql.
Thanks
The answer is, don't use SQL*Plus. Don't call a command-line utility from inside your script; between the ruby-oci8 gem and the ruby-plsql gem, you can do anything you could accomplish from within SQL*Plus.
The reason you get the errors is that you are sending each line to the shell individually. If your entire statement was wrapped in a single pair of backticks, it might work.
But if you really are unable to install the proper gems, put the commands in a temporary file and tell sqlplus to execute that, eg:
require 'tempfile'
file = Tempfile.open(['test', '.sql'])
file.puts "set serveroutput on;"
file.puts "commit;"
file.puts "insert /*+ APPEND*/ INTO table(col1, col2) values (#{data[0]},#{data[1]});"
file.puts "exit;" # needed or sqlplus will never return control to your script
file.close
output = `sqlplus user/pswd#host ##{file.path}`
file.unlink
You'll have to be very careful about:
Quoting values (if using oci8/dbi you could use bind variables)
Error handling. If using ruby libraries, errors would raise exceptions. Using sqlplus, you'll have to parse the output instead. Yuck!
So it can be done but I highly recommend you jump through whatever hoops are required to get oci8 (and maybe ruby-DBI) installed properly :)
ps are you sure you want to commit before the insert?

Getting return status AND program output

I need to use Lua to run a binary program that may write something in its stdout and also returns a status code (also known as "exit status").
I searched the web and couldn't find something that does what I need. However I found out that in Lua:
os.execute() returns the status code
io.popen() returns a file handler that can be used to read process output
However I need both. Writing a wrapper function that runs both functions behind the scene is not an option because of process overhead and possibly changes in result on consecutive runs. I need to write a function like this:
function run(binpath)
...
return output,exitcode
end
Does anyone has an idea how this problem can be solved?
PS. the target system rung Linux.
With Lua 5.2 I can do the following and it works
-- This will open the file
local file = io.popen('dmesg')
-- This will read all of the output, as always
local output = file:read('*all')
-- This will get a table with some return stuff
-- rc[1] will be true, false or nil
-- rc[3] will be the signal
local rc = {file:close()}
I hope this helps!
I can't use Lua 5.2, I use this helper function.
function execute_command(command)
local tmpfile = '/tmp/lua_execute_tmp_file'
local exit = os.execute(command .. ' > ' .. tmpfile .. ' 2> ' .. tmpfile .. '.err')
local stdout_file = io.open(tmpfile)
local stdout = stdout_file:read("*all")
local stderr_file = io.open(tmpfile .. '.err')
local stderr = stderr_file:read("*all")
stdout_file:close()
stderr_file:close()
return exit, stdout, stderr
end
This is how I do it.
local process = io.popen('command; echo $?') -- echo return code of last run command
local lastline
for line in process:lines() do
lastline = line
end
print(lastline) -- the return code is the last line of output
If the last line has fixed length you can read it directly using file:seek("end", -offset), offset should be the length of the last line in bytes.
This functionality is provided in C by pclose.
Upon successful return, pclose() shall return the termination status
of the command language interpreter.
The interpreter returns the termination status of its child.
But Lua doesn't do this right (io.close always returns true). I haven't dug into these threads but some people are complaining about this brain damage.
http://lua-users.org/lists/lua-l/2004-05/msg00005.html
http://lua-users.org/lists/lua-l/2011-02/msg00387.html
If you're running this code on Win32 or in a POSIX environment, you could try this Lua extension: http://code.google.com/p/lua-ex-api/
Alternatively, you could write a small shell script (assuming bash or similar is available) that:
executes the correct executable, capturing the exit code into a shell variable,
prints a newline and terminal character/string onto standard out
prints the shell variables value (the exit code) onto standard out
Then, capture all the output of io.popen and parse backward.
Full disclosure: I'm not a Lua developer.
yes , your are right that os.execute() has returns and it's very simple if you understand how to run your command with and with out lua
you also may want to know how many variables it returns , and it might take a while , but i think you can try
local a, b, c, d, e=os.execute(-what ever your command is-)
for my example a is an first returned argument , b is the second returned argument , and etc.. i think i answered your question right, based off of what you are asking.

Strange variable-argument problem in Capistrano Task

Hello stackoverflow experts,
I got a very strange problem in a task I'm creating with Capistrano. I'm trying to pass a variable from the command line:
>> cap create_dir -s name_of_dir=mydir
task :create_dir do
printf("#{name_of_dir}")
if !(exists?(:name_of_dir)) then
name_of_dir = Capistrano::CLI.ui.ask("Name of dir to be created.")
end
full_path = "/home/#{name_of_dir}"
run "mkdir #{full_path}"
end
The very strange this is that correctly parses the variable when I do printf, but parses as a blank(empty) string in the following command. I really find no explanation for this and I'm sure is not a stuping typo or anything like that?
I'm not expierenced in Ruby like in Java and PHP, I'm affraid that there maybe a strange rule?
Thanks!!
A few suggestions:
Avoid using variables with the same name of internal task variables
use fetch() instead of dealing with if exits? else then...
Here's the code
>> cap create_dir -s name_of_dir=mydir
task :create_dir do
printf("#{name_of_dir}")
directory = fetch(:name_of_dir) { Capistrano::CLI.ui.ask("Name of dir to be created.") }
full_path = "/home/#{directory}"
run "mkdir #{full_path}"
end
In newer versions of capistrano, at least from 2.5.19 which I run now the whole command line argument thing works different now. You call it like this.
cap command argument=value
And the syntax in the code is
ENV.has_key?('argument') and ENV['argument']
That's basically it, but you can look at my blogpost about it for a working example
It looks like in the second line you are checking if the symbol :name_of_dir exists - not the actual value of the variable name_of_dir.
Because you're unlikely to have a filename name_of_dir it will count as not existing... and then name_of_dir (the variable) is overwritten by the Capistrano::CLI.ui.ask command.
Not sure why but that must be killing it somehow.
Try removing the ":" and seeing if that fixes the problem.

Resources