wrong number of arguments (1 for 0) when running capistrano (ruby) - ruby

desc "Takes a database dump from remote server"
task :backup do
invoke 'db:backup_name'
on roles(:db) do
run "mysqldump -u #{fetch(:db_username)} -p#{fetch(:db_password)} #{fetch(:db_database)} > #{shared_path}/db_backups/#{fetch(:backup_filename)}.sql"
system('mkdir -p db_backups')
download! "#{fetch(:backup_file)}", "db_backups/#{fetch(:backup_filename)}.sql"
within release_path do
execute :rm, "#{fetch(:backup_file)}"
end
end
end
I get this error:
wrong number of arguments (1 for 0)
on this line:
run "mysqldump -u #{fetch(:db_username)} -p#{fetch(:db_password)} #{fetch(:db_database)} > #{shared_path}/db_backups/#{fetch(:backup_filename)}.sql"
If I puts the contents of this and run this on the remote server - it works fine. Really not sure why ruby throws this error.

Try using backticks instead:
`mysqldump -u #{fetch(:db_username)} -p#{fetch(:db_password)} #{fetch(:db_database)} > #{shared_path}/db_backups/#{fetch(:backup_filename)}.sql`

Related

Sort command in bash script does not work when called from Jenkins

I am trying to execute a shell script on a windows node using Jenkins.
The bash script uses sort -u flag in one of the steps to filter out unique elements from an existing array
list_unique=($(echo "${list[#]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
Note - shebang used in the script is #!/bin/bash
On calling the script from command prompt as - bash test.sh $arg1
I got the following error -
-uThe system cannot find the file specified.
I understand the issue was that with the above call, sort.exe was being used from command prompt and not the Unix sort command. To get around this I changed the path variable in Windows System variables and moved \cygwin\bin ahead of \Windows\System32
This fixed the issue and the above call gave me the expected results.
However, When the same script is called on this node using Jenkins, I get the same error again
-uThe system cannot find the file specified.
Jenkins stage calling the script
stage("Run Test") {
options {
timeout(time: 5, unit: 'MINUTES')
}
steps {
script {
if(fileExists("${Test_dir}")){
dir("${Test_dir}"){
if(fileExists("test.sh")){
def command = 'bash test.sh ${env.arg1}'
env.output = sh(returnStdout: true , script : "${command}").trim()
if (env.output == "Invalid"){
def err_msg = "Error Found."
sh "echo -n '" + err_msg + " ' > ${ERR_MSG_FILE}"
error(err_msg)
}
sh "echo Running tests for ${env.output}"
}
}
}
}
}
}
Kindly Help

Prevent Rake's sh command from echoing the command

Whenever I call sh from rake it often echos the command that will be ran right before it is run. How can I prevent sh from logging the commands to stdout. I'd like to prevent this as I have api keys in the command I am calling, and I don't want to expose them in my build log.
There are two parts to solving this. The first is to pass the verbose: false option, which will prevent the command from being printed before it's executed:
$ cat Rakefile
SECRET = 'foobarbaz'
task :foo do
sh "echo #{SECRET} > secrets.txt", verbose: false
end
$ rake foo
(no output)
However, this doesn't help if there's an error, since Rake will print the failed command if it returns an error:
$ cat Rakefile
SECRET = 'foobarbaz'
task :foo do
sh "echo #{SECRET} > secrets.txt; exit 1", verbose: false
end
$ rake foo
rake aborted!
Command failed with status (1): [echo foobarbaz > secrets.txt; exit 1...]
...
The solution is hinted at in the docs for sh:
If a block is given, upon command completion the block is called with an OK flag (true on a zero exit status) and a Process::Status object. Without a block a RuntimeError is raised when the command exits non-zero.
You can see where the default behavior comes from in the Rake source. The solution, then, is to supply our own block:
$ cat Rakefile
SECRET = "foobarbaz"
task :foo do
sh "echo #{SECRET} > secrets.txt; exit 1", verbose: false do |ok, status|
unless ok
fail "Command failed with status (#{status.exitstatus}): [command hidden]"
end
end
end
$ rake foo
rake aborted!
Command failed with status (1): [command hidden]
...
Looks good!
If you find yourself needing this in multiple places, you could write a convenience method; something like this:
def quiet_sh(*cmd)
options = (Hash === cmd.last) ? cmd.pop : {}
options = { verbose: false }.merge(options)
sh *cmd, options do |ok, status|
unless ok
fail "Command failed with status (#{status.exitstatus}): [command hidden]"
end
end
end
SECRET = "foobarbaz"
task :foo do
quiet_sh "do_secret_things"
end

How can I get the output of an ssh command?

I'd like to programmatically check if someone has their SSH keys set up correctly for GitHub. I understand that I can use `ssh -T git#github.com` in Ruby. However, I'd like to keep the ssh output in a variable.
My current code is:
github_response = `ssh -T git#github.com`
unless github_response.start_with?('Hi')
puts 'Please set up your GitHub ssh keys'
end
`ssh -T git#github.com` outputs the response (starting with "Hi"). However the github_response variable is nil.
How can I assign the output of `ssh -T git#github.com` to github_response?
Your example failed because the Hi xxx! You've successfully authenticated.... message is not from stdout, but stderr.
> require 'open3'
=> true
> stdin, stdout, stderr, wait_thr = Open3.popen3('ssh -T git#github.com')
=> [#<IO:fd 8>, #<IO:fd 9>, #<IO:fd 11>, #<Thread:0x007f89ee1149a8 sleep>]
> stdout.gets
=> nil
> stderr.gets
=> "Hi halfelf! You've successfully authenticated, but GitHub does not provide shell access.\n"
You could add -v for verbose output, it will then dump much of the connection info to stdout. From that log you can scrape to find whether the server accepted any of the keys the ssh client offered

Escaping an ampersand character ('&') in a password for a Ruby script

I have a password like 'X&Y' and I am trying to run a Ruby script that opens an SSH session, but the script breaks at the & character like :
*server: X
*server: bash: Y: command not found
Escaping the character like & doesn't help either. Ideas appreciated!
The code where it happens is at the ssh.exec:
pass="X\&Y"
Net::SSH.start( host_name, user, :password => pass ) do |ssh|
#do stuff
command = "sudo -S rm file"
cmd = "#{pass}|#{command}"
ssh.exec(cmd) do |ch, stream, data|
puts "*server:" + data.inspect
end
end
You can use ssh like without & getting any special meaning:
ssh -t -t user#localhost "echo 'abc&def'"
abc&def
Connection to localhost closed.

does %x[] catch all output?

If I run this code:
svn_output = %x[svn update /Users/radek/Sites/db2.rft -r 11105 --force ]
puts
puts " output is =#{svn_output}="
I get this result
svn: Working copy '/Users/radek/Sites/db2.rft' locked
svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)
output is ==
but I want the error message from svn inside the variable svn_output. Is that possible?
You want to redirect stderr to stdout:
svn_output = %x[svn update /Users/radek/Sites/db2.rft -r 11105 --force 2>&1]
puts
puts " output is =#{svn_output}="

Resources