run a remote ruby script (pass parameters as well) using ssh - ruby-on-rails

I want to connect to a remote host and run a ruby script on the remote host. Following is the code that I am using -
ssh = Net::SSH.start(host, user)
args = "some argument" //can be any data type, list, string, anything
results = conn.exec!('ruby runfile.rb args')
It's not passing args to the file in this case. I have also tried using double quotes instead of single quotes. How do I send the parameters as well?

the name of the connection variable must be consistent (ssh ≠ conn).
You need to send the content of args instead of the string "args":
Double quotes are needed for the #{...} syntax to work. Or use 'ruby runfile.rb ' + args if you prefer.
Use # instead of // to comment Ruby code.
Use .shellescape to harden against unwanted (accidental or malicious) effects in the remote shell.
This code does work:
require 'net/ssh'
require 'shellwords'
ssh = Net::SSH.start(host, user)
args = "some argument".shellescape #can be any data type, list, string, anything
results = ssh.exec!("ruby runfile.rb #{args}")
puts results

Related

Got the error when use LUA script to query a list

when I use Lua script to query a list, I got the correctly result if the list is not empty. But got error if the list is empty.
Blow is my script:
const char * sLuaQueryServers = "local key_list = redis.call('KEYS',
KEYS[1]); return(redis.call('MGET', unpack(key_list)))";
I passed the "serverlist:*" as the key, it's successfully returned the server in list.
But if there no server in redis, I got below error:
ERR Error running script (call to
f_88620231033e13635dc3181f2947a740f91012dc): #user_script:1: #user_script:
1: Wrong number of args calling Redis command From Lua script
"
Please help.
To your question, add a check that the list isn't empty before calling MGET, e.g.:
local key_list = redis.call('KEYS', KEYS[1])
if #key_list > 0 then
return(redis.call('MGET', unpack(key_list)))
else
return nil
end
Note #1: no need for semicolons in Lua
Note #2: Using KEYS isn't recommended for anything, except debugging
Note #3: You're using the KEYS table to pass an argument, but since your script is running KEYS (the command) that's really a moot point

Aurora: Unknown schema in docker parameters

I have an aurora file which contains this docker parameters:
jobs = [
Service(cluster = 'mesos-fr',
environment = 'devel',
role = 'root',
instances = 1,
name = 'frontend_service',
task = run_frontend_service,
container=Docker(image='frontend_service', parameters=[{'name': 'frontend_service'}, {'publish': '{{thermos.ports[http]}}:3000'}])
)
]
Got this error:
Error loading configuration: Unknown schema attribute publish
Is there a solution for connecting the host port with a docker container port?
EDIT: Mustache variable replacements might not help since they happen after the container comes up.
It looks like there's a problem with the form of your Docker Parameters. An example of correct ones is container=Docker(image='nginx', parameters=[Parameter(name='env', value='HTTP_PORT={{thermos.ports[http]}')]).
There is a Parameter object, with name and value. Value can be a string with mustache variable (like ports) so you can throw that stuff in there.
This documentation (under Announcer Objects) might help too: http://aurora.apache.org/documentation/latest/reference/configuration/

Bad result from groovy's ProcessGroovyMethods (UNIXProcess)

While using Grails 2.4.5 org.codehaus.groovy.runtime.ProcessGroovyMethods on Ubuntu 14.04:
def command = "mysqldump -h${databaseProperties.host} -u'${databaseProperties.username}' -p'${databaseProperties.password}' ${databaseProperties.name} " + table
print command
def proc = command.execute()
def oneMinute = 60000
proc.waitForOrKill(oneMinute)
if(proc.exitValue()!=0){
println "[[return code: ${proc.exitValue()}]]"
println "[[stderr: ${proc.err.text}]]"
return null
}else{
return proc.in.text.readLines()
}
I've got
[[return code: 2]]
[[stderr: mysqldump: Got error: 1045: Access denied for user 'root'#'localhost' (using password: YES) when trying to connect]]
but when I copy-paste printlined command into my bash I receive proper dump. What is going on?
I've also tried:
changing mysqldump to full path: /usr/bin/mysqldump
sending arguments as a String array but with the same
result.
sending command as a regular String to execute:
"mysqldump -hlocalhost -u'root' -p'password' database table"
it works in system bash, it doesn't as a ProcessGroovyMethod...
Update:
After thinking about this overnight, I'm (still) convinced that the problem is related to your password. Since it's really not a best practice to provide the password on the command line (mysqldump even warns you about this), I think you should change tactics by creating a login-path.
Use the following command to create a login path (this is a one-time step):
mysql_config_editor set --login-path=name --host=localhost --user=youruser --password
Then change the command you're attempting to execute from Groovy to this:
def command="mysqldump --login-path=name database table"
This will work around the issue you're seeing and is more secure.
Original answer:
I was able to replicate the problem. String.execute() doesn't use a command shell, and therefore the single quotes are getting passed to mysqldump as if they were part of your password.
Edit: After some further thought, I don't think Groovy's String.execute() is the way to go here, because of its unexpected handling of quotes. It's fine if your password doesn't include spaces, but this is likely to be brittle.
If you need more control, you should consider using ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder("mysqldump", "-h${databaseProperties.host}", "-u${databaseProperties.username}", "-p${databaseProperties.password}", databaseProperties.name, table);
pb.inheritIO();
Process p = pb.start();
Edit: Further research, just tested this with a password that includes spaces. command.execute() doesn't handle this properly, but using the ProcessBuilder method works.
Here's another post explaining some of the unexpected behavior of the String.execute() method:
Groovy: strings with embedded quotes don't execute as expected

SQLPlus: using special character for password in script

I have issue with special character in password - '#'.
Issue that i don't know how to pass password with this special character to script file and connect using sqlplus.
For example i have user 'test_user' with password 'temp123#'. For login via sqlplus i use following string with escaping: sqlplus test_user/\"temp123#\"#some-db:1521/SID
It's works well. For my case i need to pass password as parameter for sql script. For example, i have following script to connect (actually script using several pairs of login/password to update many users at once):
-- #deploy.sql
connect &&2./&&3.#&&1.
At have failure with that because password with '#' can't interpreted correctly by sqlplus. I tried many advices from google with escaping but mostly of them applicable for connect string at sqlplus invoke. For my case its required for parameter that passed to script.
use : cmd.exe and not powershell window
if not :
in powershell windows : sqlplus 'login/\"P#$$w0rd\"#TNS_NAME'
in cmde.exe : sqlplus login/\"P#$$w0rd\"#TNS_NAME
Just quotes required in connect string:
connect &&2./"&&3."#&&1.

Ruby : Pass array in command line argument

I want to pass array in argument in such a way suppose process.rb is my script and the argument will be like:
i/p
process.rb server{1..4}
process.rb prodserver{2..3}
process.rb devserver3
The process.rb should accept all the inputs and parse it in such a way that when I print the variable which holds the arguments give me below result.
o/p
puts arguments
server1
server2
server3
server4
or
prodserver2
prodserver3
or
devserver3
I have a shell script which does the same:
for i in "$#"
do
echo $i
done
i/p
server{1..4}
o/p
server1server2server3server4
I wanted to have the same logic in the ruby.
Since I am a new bie in ruby I am not able to find the same on google.
Please let me know how I can get this output or any article about the related to my question
The list is expanded by the shell before it ever hits your script. In other words, both your shell script and your Ruby script do not receive a single argument server{1..4} but rather they receive four arguments server1 server2 server3 server4, before they even start interpreting the arguments themselves.
You can simply just iterate over those, there is no need to parse the {1..4} shell expansion syntax yourself because you will never see it! It is already parsed and expanded by the shell before the shell passes off the arguments to your script.
ruby -e 'p ARGV' -- server{1..4}
# ["server1", "server2", "server3", "server4"]
#!ruby
ARGV.each do |i|
puts i
end
Basically ARGV holds all arguments passed to program, and puts prints string with new line added (the same as echo without -n flag in shell).
Command-line arguments in Ruby end up in ARGV. You can duplicate your shell script's functionality by iterating over that:
ARGV.each do |a|
puts a
end
If I understand you correctly you want to expand the range that comes in string form from your argument ARGV[0] ? My samples use a string to demonstrate it workd, replace the string by ARGV[0]
def expand_range arg
string, range = arg.split("{") #split arg in string part and rangestring part
if range #if a range is given
# parse the rangestring to an range by splitting the string on ..
# and splash this array to both its elements, convert them to integer
# and transform into a real range
# and enumerate each number in the range
Range.new(*range.split("..").map(&:to_i)).each do |val|
#concatenate the string part with the number
p "#{string}#{val}"
end
else #else just pass the string
p string
end
end
expand_range 'server{1..4}'
# "server1"
# "server2"
# "server3"
# "server4"
expand_range 'devserver3'
#"devserver3"
Personally I would return an array and print that instead of printing in the method itself, that would be more multifunctional.

Resources