I have an issue about executing shell commands on a remote server.
I'm trying various solutions and I have one working but it is not optimized in terms of maintenance : I use a batch file that launches putty which connects to the remote server ans sends the command.
ie. in groovy :
def batchFile = "C:\\Validation\\Tests_Auto\\Scripts\\remote_process\\setOldDate.bat"
Runtime.runtime.exec(batchFile)
and in my batch file :
c:
cd C:\Validation\Tests_Auto\Scripts\remote_process\
putty.exe -ssh root#xx.xx.xx.xx -pw **** -m "C:\Validation\Tests_Auto\Scripts\remote_process\setOldDate.txt"
setOldDate.txt contains the command date -s #1522018800
This works. However I'd like to launch it in a cleaner way, either avoiding the use of text file for the command or, better, avoiding using putty.
I tried several another way to do the same thing but it doesn't work. I think I'm not too far but I need a little help.
I tried to launch a direct command via ssh:
Runtime.getRuntime().exec('"c:\\Program Files\\OpenSSH\\bin\\ssh.exe" root:****#xx.xx.xx.xx date -s #1522018800')
I'd be grateful if anyone could help
thanks
#Grab(group='com.jcraft', module='jsch', version='0.1.54')
def ant = new AntBuilder()
ant.sshexec( host:"somehost", username:"dude", password:"yo", command:"touch somefile" )
for other sshexec and scp tasks parameters see doc:
https://ant.apache.org/manual/Tasks/sshexec.html
https://ant.apache.org/manual/Tasks/scp.html
for soapui
this method using apache ant + jsch-0.1.54.jar
the only way i know for soapui:
download the following libraries and put them into soapui\bin\endorsed directory (create the endorsed directory)
https://central.maven.org/maven2/org/apache/ant/ant/1.9.11/ant-1.9.11.jar
https://central.maven.org/maven2/org/apache/ant/ant-launcher/1.9.11/ant-launcher-1.9.11.jar
https://central.maven.org/maven2/com/jcraft/jsch/0.1.54/jsch-0.1.54.jar
edit the soapui\bin\soapui.bat and add the following line where other JAVA_OPTS are defined:
set JAVA_OPTS=%JAVA_OPTS% -Djava.endorsed.dirs="%SOAPUI_HOME%endorsed"
that's because ant libs must be loaded before groovy.
then the code above should work in soapui (except #Grab)
Alternatively you can download only jsch-XXX.jar into existing soapui\bin\ext directory and use jsch library directly from groovy
see examples: http://www.jcraft.com/jsch/examples/
or search for groovy jsch examples
Finally, compiling my various research and struggling to fit my environment constraints (groovy in soapui), I ended up with the following solution that works for me :
download jsch-0.1.54.jar and set it in C:\Program Files\SmartBear\ReadyAPI-2.3.0\bin\ext
use the following groovy script :
import java.util.Properties
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.JSch
import com.jcraft.jsch.Session
def ip = context.expand( '${#Project#projectEndpoint}' )
try
{
JSch jsch = new JSch();
Session session = jsch.getSession("root","$ip", 22);
session.setPassword("****");
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
ChannelExec channelssh = (ChannelExec)session.openChannel("exec");
// Execute command
//channelssh.setCommand("date -s #1520018000"); // change date
channelssh.setCommand("ntpdate -u pool.ntp.org"); // restore date
channelssh.connect();
channelssh.disconnect();
}
catch (Exception e)
{
log.info "exception : " + e
System.out.println(e.getMessage());
}
finally
{
session.disconnect();
}
UPGRADE
Here is a generalization I've made as my needs evolved. The following script, still using jsch allows to send any command.
This deals with host checking and eliminates hazards due to no host checking.
User and password are passed as parameters
import java.util.Properties
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.JSch
import com.jcraft.jsch.Session
import java.util.regex.Pattern
def ip = context.expand( '${get endpoint#endpoint}' )
ip = ip.replaceFirst("http[s]?://","")
def user = context.expand( '${#Project#ssh_user}' )
def password = context.expand( '${#Project#ssh_password}' )
def command = context.expand( '${#TestCase#command}' )
def timeout = context.expand( '${#TestCase#timeout_ms}' )
if (timeout == "")
timeout = 1000 // default timeout 1s
else
timeout = timeout.toInteger()
log.info "command = " + command
Session session
try
{
JSch jsch = new JSch();
session = jsch.getSession(user,ip, 22);
session.setPassword(password);
//log.info "user : $user"
//log.info "set password : $password"
//log.info System.getProperty("user.home")+"/.ssh/known_hosts"
jsch.setKnownHosts(System.getProperty("user.home")+"/.ssh/known_hosts");
session.connect();
//log.info "session connect"
// SSH Channel
ChannelExec channelssh = (ChannelExec)session.openChannel("exec");
// Execute command
channelssh.setCommand(command);
InputStream commandOutput = channelssh.getInputStream();
channelssh.connect();
int readByte = commandOutput.read();
outputBuffer = [];
// timeout to avoid infinite loop
while((readByte != -1) && (timeout > 0))
{
outputBuffer.add(readByte)
readByte = commandOutput.read();
timeout = timeout -1
}
// process output
outputBuffer = outputBuffer as byte[]
// convert byte array into string
output = new String(outputBuffer, "UTF-8")
sleep(3000)
//log.info "disconnect"
channelssh.disconnect();
testRunner.testCase.setPropertyValue("cmd_output", output)
}
catch (Exception e)
{
msg = "exception : " + e
log.error msg
testRunner.fail(msg)
}
finally
{
session.disconnect();
}
Related
The groovyscript below is used to get file from remote machine using sftp. I need to get the file using sftp
import groovy.json.JsonSlurper
import com.jcraft.jsch.*
java.util.Properties config = new java.util.Properties()
config.put "StrictHostKeyChecking", "no"
JSch ssh = new JSch()
def rfile = "/path/to/remote/file/on/remote/host";
Session sess = ssh.getSession 'user','host', 22
sess.with {
setConfig config
setPassword password
connect()
Channel chan = openChannel "sftp"
chan.connect()
ChannelSftp sftp = (ChannelSftp) chan;
def flowFile = session.get()
if(!flowFile) return
flowFile.write{rawIn, rawOut->
def keyValueList = rawIn.withReader("UTF-8"){ new JsonSlurper().parse(it) }
sftp.get("rfile/abc.txt").withReader("UTF-8"){reader->
rawOut.withWriter("UTF-8"){writer->
reader.eachLine{line->
keyValueList.each{ if(it.Key) line = line.replaceAll(it.Key, it.Value) }
writer << line << '\n'
}
}
}
}
chan.disconnect()
disconnect()
REL_SUCCESS << flowFile
}
Getting error:
unable to resolve class JSch # line 7, column 6. JSch ssh = new JSch() org.codehaus.groovy.syntax.SyntaxException
I am using import import com.jcraft.jsch.* but it seems JSch class is not available or import is not proper.
you have to download jsch libraries from http://www.jcraft.com/jsch/ and put jars into nifi/lib directory
or if your nifi server has access to internet you could use this script annotation to download library from public repository
#Grab(group='com.jcraft', module='jsch', version='0.1.55')
import com.jcraft.jsch.*
...
I'm trying to configure Jenkins build trigger from Jira post-function Groovy script
Here is my Groovy code:
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.fields.CustomField;
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
def WANITOPUSHField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(10802);//customfield id
def WANITOPUSHValue = issue.getCustomFieldValue(WANITOPUSHField);
def SelectVersionField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(10805);//customfield id
def SelectVersionValue = issue.getCustomFieldValue(SelectVersionField);
if(WANITOPUSHField != null) {
if(WANITOPUSHValue.toString() == 'Yes') {
'curl --user USERNAME:PASSWORD "http://JENKINS_URL/job/deploy-dev-test/buildWithParameters?token=MYTOCKEN&ENV=1"'.execute()
UserMessageUtil.success("Jenkins Build started ");
} else {
UserMessageUtil.success("Condition Not sucsess "+WANITOPUSHValue.toString());
}
}
Here I have used curl command to trigger Jenkins build if the Jira ticket status changed, but the curl command is not working here
It is throwing output on the alert box
java.lang.UNIXProcess#4d0c79da
I don't know what its mean whether the command is executing successfully or not, Please anyone can help me on this and suggest me if I can use some different method with Groovy to achieve this
"something".execute() returns instance of UNIXProcess java class. When toString() method is not overriden you will see something like java.lang.UNIXProcess#4d0c79da
Here some code which will help you to get shell command output:
def command = 'curl --user USERNAME:PASSWORD "http://JENKINS_URL/job/deploy-dev-test/buildWithParameters?token=MYTOCKEN&ENV=1"'
def proc = command.execute()
proc.waitFor()
println "Process exit code: ${proc.exitValue()}"
println "Std Err: ${proc.err.text}"
println "Std Out: ${proc.in.text}"
I am executing following groovy script in my soapui assertion where I am trying to store the value of the output of linux command into a variable so that I cam compare the output of linux command with expected value.My groovy is as below
import groovy.sql.Sql
import java.sql.DriverManager
import java.sql.Connection
import javax.sql.DataSource
import java.sql.Driver;
import java.util.*;
import java.text.*;
// Executing Script to capture logs
log.info "Executing Script to capture logs"
import java.lang.Object
import com.jcraft.jsch.JSch
import com.jcraft.jsch.Session
import com.jcraft.jsch.UserInfo
import com.jcraft.jsch.Channel
import com.jcraft.jsch.ChannelExec
import java.util.Properties
def sshHost = context.expand('${#Project#Kcom}');
def sshUser = 'sshuser'
def sshPass = 'sshpass'
def sshPort = port value
/////////////////////////////
log.info "Opening connection to ${sshUser}#${sshHost}:${sshPort}"
Properties config = new Properties()
config.put("StrictHostKeyChecking", "no")
JSch jsch = new JSch()
///////////////////////////
Session s = jsch.getSession(sshUser, sshHost, sshPort)
s.setPassword(sshPass)
s.setConfig(config)
s.connect()
log.info "Connected"
Channel c = s.openChannel("exec");
ChannelExec ce = (ChannelExec) c;
def logerror = ce.setCommand("tail -50 <log file> | grep -i 'some string'");
log.info logerror
ce.setErrStream(System.err);
ce.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(ce.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
log.info(line);
}
here logerror always returns null .
how can i do this?
i don't know what's wrong with your code, i just know that ant command sshexec do what you need.
so, you can see how to do it correctly by sources
ps: i know that soapui includes limited groovy-all.jar but if you able to add full groovy library list into soapui classpath it'll possible to use groovy.lang.AntBuilder():
def ant = new AntBuilder()
ant.sshexec(
host:"somehost",
username:"dude",
password:"yo",
command:"tail -50 <log file> | grep -i 'some string'",
output: "path/to/local/output/file"
)
I am trying execute a bash script from my grails app. The script has a ssh call in it. I am using keys to connect between servers.
If I run the script via CLI it works as expected but when I run it via the grails app the script runs but only the part that deals with the local machine. I do not see any output from the remote script.
Any help in pointing me in the right direction will be appreciated.
Bash Script:
echo "Starting Data pushed..."
ssh -t -i /path/to/.ssh/id_rsa_remote_user remote_user#remote_server 'sudo /opt/remote_user/script.sh'
echo "Starting Data pushed... Done!"
Grails/Groovy code:
class CommonService {
def executeScript(String script, Integer waitTimeInMinutes = 1){
def sout = new StringBuilder()
def serr = new StringBuilder()
Integer exitCode = -1
def proc
try {
proc = script.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(waitTimeInMinutes * 60 * 1000)
exitCode = proc.exitValue()
}
catch(e){
log.error e.printStackTrace()
serr << e.toString()
}
log.info "Executed Script: ${sout}"
log.info "Executed Script Extended Output: \n${serr}"
return [output: sout, error: serr, exitCode: exitCode]
}
}
Map outcome = commonService.executeScript('/path/to/local/scripts/pushToProduction.sh', waitTime)
I have prepared a test case in SoapUI Open Source which loops over values in csv file and sends request for each set of values (taken care of by groovy script). I want to modify it so each thread for each new iteration uses value from next row of csv file.
import com.eviware.soapui.impl.wsdl.teststeps.*
def testDataSet = []
def fileName = "C:\\sSHhrTqA5OH55qy.csv"
new File(fileName).eachLine { line -> testDataSet.add( line.split(",") ) }
def myProps = new java.util.Properties();
myProps = testRunner.testCase.getTestStepByName("Properties");
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
def testCase = testRunner.testCase;
def testStep = testCase.getTestStepByName("TestRequest");
testRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testCase, null);
testStepContext = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext(testStep);
while (true) {
for ( i in testDataSet ) {
myProps.setPropertyValue("parameter0",i[0]);
myProps.setPropertyValue("username",i[1]);
myProps.setPropertyValue("parameter1",i[2]);
myProps.setPropertyValue("password",i[3]);
testStep.getTestRequest().setUsername(myProps.getPropertyValue("username"))
testStep.getTestRequest().setPassword(myProps.getPropertyValue("password"))
testStep.run(testRunner, testStepContext);
}
}
I want to modify this script so each thread from the pool gets unique (next) unused value from data source
I tried to use newFixedThreadPool from java.util.concurrent as suggested here (Concurrency with Groovy), however I can't get it to work - either requests are duplicated or SoapUI crashes (I am new to concurrency).
Can you please help me to get it right?
I think this would work for you:
while (true) {
for ( i in testDataSet ) {
def th = Thread.start(){
myProps.setPropertyValue("parameter0",i[0]);
myProps.setPropertyValue("username",i[1]);
myProps.setPropertyValue("parameter1",i[2]);
myProps.setPropertyValue("password",i[3]);
testStep.getTestRequest().setUsername(myProps.getPropertyValue("username"))
testStep.getTestRequest().setPassword(myProps.getPropertyValue("password"))
testStep.run(testRunner, testStepContext);
}
th.join()
}
So, new threads would be created on each loop.
If you wanted to test out if its working you could place loginfo(s) in the code...
log.info("Thread Id: " + Thread.currentThread().getId() as String)
I don't see your point. SoapUi already gives you a datasource test step that accepts a csv file as input.
So once you have all these values you can transfer the properties and run the test.